embedding and extending python C API registering callback handler objects

Matimus mccredie at gmail.com
Fri Jun 27 18:03:05 CEST 2008


On Jun 27, 8:22 am, Tim Spens <t_sp... at yahoo.com> wrote:
> Hello all,
>
> I've been trying to get an example found herehttp://codeidol.com/python/python3/Embedding-Python/Registering-Callb...
> to work.  Every thing works fine except when I try to trigger an event from c that will call a python function.  Here is my test code:
>
> //-----------------------python code--------------------------//
> #! /usr/bin/env python
> import time
> import callback
>
> def callback1(label,count):
>         print 'callback1 successfully triggered from python via callback.so'
>         return 'callback1 => %s number %i' % (label, count)
>
> def callback2(label,count):
>         return 'callback2 => ' +  label * count
>
> print '\nTest1:'
> callback.setHandler(callback1)
> callback.triggerEvent()         # simulate events caught by C layer
>
> print '\nTest2:'
> callback.setHandler(callback2)
>
> print 'Waiting for callback2 to be called from c:'
> while 1:
>         time.sleep(.001)
>
> //-----------------------c code-------------------------------//
> #include <Python.h>
> #include <stdlib.h>
>
> /* keep Python object in C */
> static PyObject *Handler = NULL;
>
> void Route_Event(char *label, int count){
>     char *cres;
>     PyObject *args, *pres;
>     /* call Python handler */
>     args = Py_BuildValue("(si)", label, count);
>     pres = PyEval_CallObject(Handler, args);
>     Py_DECREF(args);
>     if (pres != NULL){
>         /* use and decref handler result */
>         PyArg_Parse(pres, "s", &cres);
>         printf("%s\n", cres);
>         Py_DECREF(pres);
>
> }}
>
> // the actual python callback call
> static PyObject *
> make_call(PyObject *function, PyObject *args){
>     if (function == NULL) return NULL;
>     PyObject * val = PyObject_CallObject(function, args);
>     Py_XDECREF(args);
>     return val;
>
> }
>
> static PyObject *
> Register_Handler(PyObject *self, PyObject *args){
>     /* save Python callable object */
>     Py_XDECREF(Handler);
>     PyArg_Parse(args, "O", &Handler);
>     Py_XINCREF(Handler);
>     Py_INCREF(Py_None);
>     return Py_None;
>
> }
>
> static PyObject *
> Trigger_Event(PyObject *self, PyObject *args){
>     /* let Python simulate event caught by C */
>     static int count = 0;
>     Route_Event("spam", count++);
>     Py_INCREF(Py_None);
>     return Py_None;
>
> }
>
> static struct PyMethodDef callback_methods[] = {
>     {"setHandler",    Register_Handler},       /* name, address */
>     {"triggerEvent",  Trigger_Event},
>     {NULL, NULL}};
>
>                                       /* on first "import callback" */
> void initcallback(){                  /* this is called by Python  */
>     (void) Py_InitModule("callback", callback_methods);
>
> }
>
> int main(){
>         while (1){
>                 printf("1\n");
>                 //attempting to call callback2 which is registered to Handler
>                 //i've also tried args = Py_BuildValue("(si)", label, count); here but I get a segfault.
>                 PyObject *args = Py_BuildValue("s","c code");
>                 printf("2\n");
>                 PyObject* val = make_call(Handler,args);
>                 printf("3\n");
>             Py_XDECREF (val);
>             printf("4\n");
>                 sleep(1);
>
> }}
>
> //------------------------compiler stuff----------------------//
> gcc callback.c -c -g -Wall -fpic -I /usr/include/python2.5 -o callback.o
> gcc callback.c -g -Wall -I /usr/include/python2.5 -L /usr/local/lib -lpython2.5 -o callback
> gcc -shared -Wall callback.o -o callback.so
>
> //------------------------test code results-------------------//
> ../callback.py
> Test1:
> callback1 successfully triggered from python via callback.so
> callback1 => spam number 0
>
> Test2:
> Waiting for callback2 to be called from c:
> #NOTHING EVER GETS PRINTED HERE CALLBACK NEVER GETS CALLED?
>
> ../callback
> 1
> 2
> 3
> 4
> ....
>
> Thanks,
> Tim

Maybe you just need to flush the stdout buffer in python.
`sys.stdout.flush()`

Matt



More information about the Python-list mailing list