Author: ArcRiley
Date: 2009-02-26 17:56:11 -0500 (Thu, 26 Feb 2009)
New Revision: 1530

Added:
   trunk/concordance/src/_core/step.c
Modified:
   trunk/concordance/src/_core/__init__.c
Log:
beginning work on python callbacks

Modified: trunk/concordance/src/_core/__init__.c
===================================================================
--- trunk/concordance/src/_core/__init__.c      2009-02-26 22:56:08 UTC (rev 
1529)
+++ trunk/concordance/src/_core/__init__.c      2009-02-26 22:56:11 UTC (rev 
1530)
@@ -38,6 +38,7 @@
 
 
 static PyMethodDef concord_Methods[] = {
+  { "step", concordStep, NULL, NULL },
   { NULL, NULL }
 };
 

Added: trunk/concordance/src/_core/step.c
===================================================================
--- trunk/concordance/src/_core/step.c                          (rev 0)
+++ trunk/concordance/src/_core/step.c  2009-02-26 22:56:11 UTC (rev 1530)
@@ -0,0 +1,132 @@
+/*
+# Concordance XMPP Service Framework
+#
+# Copyright (C) 2009 Copyleft Games Group
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU Affero General Public License as published
+#  by the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU Affero General Public License for more details.
+#
+#  You should have received a copy of the GNU Affero General Public License
+#  along with this program; if not, see http://www.gnu.org/licenses
+#
+# $Id: Core.c 1485 2009-01-17 03:19:45Z ArcRiley $
+*/
+
+#include "concordance.h"
+
+static PyObject*
+concordStep() {                                                           /*\
+  cdef :                                                                  \*/
+    concordCore_Object*    self = (concordCore_Object*) s;
+    PyObject*              output;
+    concordCore_QueueMsg*  popped;
+    GTimeVal               popEnd;
+
+  /* calculate end time to wait for next callback, 0.5 seconds ahead
+
+      void              g_get_current_time       (GTimeVal *result);
+      void              g_time_val_add           (GTimeVal *time_,
+                                                  glong microseconds);
+  */
+  g_get_current_time(&popEnd);
+  g_time_val_add(&popEnd, 50000);
+
+  /* release the GIL while waiting for the next callback
+
+      gpointer       g_async_queue_timed_pop  (GAsyncQueue *queue,
+                                              GTimeVal *end_time);
+  */
+  Py_BEGIN_ALLOW_THREADS
+  popped = g_async_queue_timed_pop(self->queueRecv, &popEnd);
+  Py_END_ALLOW_THREADS
+
+  /* return if the pop call timed out */
+  if (!popped)
+    return;
+
+  /* call our handler
+
+      PyObject*      PyObject_CallMethod      (PyObject *o,
+                                              char *method,
+                                              char *format, ...)
+
+      O (object) [PyObject *]
+        Pass a Python object untouched (except for its reference count,
+        which is incremented by one). If the object passed in is a NULL
+        pointer, it is assumed that this was caused because the call
+        producing the argument found an error and set an exception.
+        Therefore, Py_BuildValue will return NULL but won’t raise an
+        exception. If no exception has been raised yet, SystemError is set.
+
+      U# (string) [char *, int]
+        Convert a C string and its length to a Python unicode object. If the
+        C string pointer is NULL, the length is ignored and None is returned.
+  */
+  output = PyEval_CallMethod(s, "clientHandle", "OU#",
+                              popped->session->self,
+                              popped->message->str, popped->message->len);
+
+  if (!output) {
+    /* free message struct and exit here if callback raised an error */
+    concordCore_queueFreeMsg(popped);
+    break;
+  }
+
+  /* if output is None, decref it, free message struct, and continue */
+  if (output == Py_None) {
+    Py_DECREF(output);
+    concordCore_queueFreeMsg(popped);
+    continue;
+  }
+
+  /* ensure output is PyUnicode_Type (since it's not None)
+
+      int            PyUnicode_Check          (PyObject *o);
+  */
+  if (!PyUnicode_Check(output)) {
+    /* free whatever was returned and raise an error
+
+        void         Py_DECREF                (PyObject *o);
+        void         PyErr_SetString          (PyObject *type,
+                                              const char *message);
+    */
+    Py_DECREF(output);
+    concordCore_queueFreeMsg(popped);
+    PyErr_SetString(PyExc_TypeError,
+                    "handle must return a Unicode string or None");
+    return NULL;
+  }
+
+  /* only use output when non-empty
+
+      Py_ssize_t     PyUnicode_GetSize        (PyObject *unicode);
+  */
+  if (PyUnicode_GetSize(output)) {
+    /* convert unicode to utf8, reusing popped->message for response
+
+        GString*     g_string_assign          (GString *string,
+                                              const gchar *rval);
+        void         g_async_queue_push       (GAsyncQueue *queue,
+                                              gpointer data);
+    */
+    popped->message = g_string_assign(popped->message,
+                                      concordPyUnicodeToUTF8(output));
+    g_async_queue_push(self->queueSend, popped);
+  }
+  else
+    /* free message struct since we didn't use it */
+    concordCore_queueFreeMsg(popped);
+
+  /* free the output object
+
+      void           Py_DECREF                (PyObject *o);
+  */
+  Py_DECREF(output);
+}

_______________________________________________
PySoy-SVN mailing list
PySoy-SVN@pysoy.org
http://www.pysoy.org/mailman/listinfo/pysoy-svn

Reply via email to