embedding and extending python C API registering callback handler objects

Tim Spens t_spens at yahoo.com
Fri Jun 27 18:57:06 CEST 2008




--- On Fri, 6/27/08, Tim Spens <t_spens at yahoo.com> wrote:

> From: Tim Spens <t_spens at yahoo.com>
> Subject: Re: embedding and extending python C API registering callback handler objects
> To: python-list at python.org, "Matimus" <mccredie at gmail.com>
> Date: Friday, June 27, 2008, 9:16 AM
> thanks, but didn't fix the problem.
> 
> 
> --- On Fri, 6/27/08, Matimus <mccredie at gmail.com>
> wrote:
> 
> > From: Matimus <mccredie at gmail.com>
> > Subject: Re: embedding and extending python C API
> registering callback handler objects
> > To: python-list at python.org
> > Date: Friday, June 27, 2008, 9:03 AM
> > 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
> > --
> > http://mail.python.org/mailman/listinfo/python-list
> 
> 
>       
> 
> --
> http://mail.python.org/mailman/listinfo/python-list

I think I know where the problem is but I'm unsure how to fix it.  When I call Register_Handler(...) from python via callback.setHandler1(callback1) this only seems to affect pythons ability to trigger an "event" in c. PyObject *Handler is always NULL even after I call Register_Handler(...).  I thought there was some magic here that was assigning the pointer *Handler to my python callback1 handler so it could be triggered from c?

-Tim


      




More information about the Python-list mailing list