[Pyrex] python callback appended to external C struct

Elias Pschernig elias at users.sourceforge.net
Thu Dec 1 16:22:33 CET 2005


Hi, after some fiddling, I got my external library to call back a python
method, but I had to actually wrap an external struct into another
struct with an extra "void *" at the end. Anyone knowing internals of
Pyrex/Python can confirm that this should be safe to use? And is this a
good way, or is there a better one?

---- cwrap.c ----
#include "cwrap.h"
void cwrap_test(CWrapPosition *self)
{
    self->cb(self);
}

---- cwrap.h ----
typedef struct CWrapPosition CWrapPosition;
struct CWrapPosition
{
    void (*cb)(CWrapPosition *self);
};
void cwrap_test(CWrapPosition *self);

---- wrap.pyx ----
cdef extern from "cwrap.h":
    ctypedef struct CWrapPosition:
        void *cb
    void cwrap_test(CWrapPosition *self)

cdef struct CWrapPositionPyrex:
    CWrapPosition wrapped
    void *self # any other way to do it?

cdef dummy_cb(CWrapPositionPyrex *wrapped):
    self = <object>wrapped.self # will this always work?
    self.cb()

cdef class Wrap:
    cdef CWrapPositionPyrex wrapped

    def __new__(self):
        self.wrapped.wrapped.cb = <void *>dummy_cb
        self.wrapped.self = <void *>self

    def test(self):
        # actually, the cb will get called by the external library
        # at undefined times (but from the same thread)
        cwrap_test(&self.wrapped.wrapped)

--- test.py ----
import wrap

class MyPythonClass(wrap.Wrap):

    def cb(self):
        print "hello from", self.name

my_python_object = MyPythonClass()
my_python_object.name = "my_python_object"
my_python_object.test()

-- 
Elias Pschernig




More information about the Pyrex mailing list