[Cython] problem with public C API for Python-implemented library
Daniele Pianu
muogoro at gmail.com
Wed Jan 28 12:36:54 CET 2009
Hi to all!!!! In my recent project I'm working to allow a C user to
work with a Python Module which presents a C API but it's mainly
implemented writing Python code. The data structure passed between C
API calls might be a C structure containing Python objects as fields.
Here an example:
ctypedef public struct SpamManager:
PySpam wrapper
cdef public api SpamManager* SpamManager_new():
# Alloc and return a SpamManager structure
....
cdef public api int SpamManager_init( SpamManager* self, Spam* instance ):
.....
# Init the wrapper with the given instance
self.wrapper = PySpam( instance )
....
cdef public api int SpamManager_doSomething( SpamManager* self ):
# Do something with my nice wrapper :)
......
cdef public api void SpamManager_clear( SpamManager* self ):
# Clear structure
....
cdef public api void SpamManager_delete( SpamManager* self ):
# Delete structure
....
Spam is a C structure and PySpam is the correspondent Cython extension
type (or the Python wrapper, as you prefer :) ). The wrapper is
initialized passing a C instance to the constructor (casting the
instance to an unsigned long to obtain the pointer address). The
SpamManager module works with the PySpam wrapper but allows a C user
to
interact with the Python wrapper using the SpamManager structure and
function calls. The SpamManager structure must contain a PySpam field,
so we can avoid the overhead of the wrapper initialization creating it
only in the initialization phase (that is, in the SpamManager_init
function call).
The problem is that, in Cython, ctypedef-ed structures cannot have an
object field (so my SpamManager definition raises a compiler error).
I've partially rounded on the error declaring the wrapper attribute in
the SpamManager structure as a PyObject*, but this trick force me to
continually cast the wrapper attribute to <obejet> every time I need
to call a PySpam method using the wrapper instance. There's also the
problem that I've to allocate the wrapper like this:
....
tmp = PySpam( instance )
self.wrapper = <PyObject*>tmp
....
tmp is a temporary Python object, so it goes out of scope when the
function terminates and, consequently, I've to manage wrapper's
reference count.
Is there a way to declare a C structure which has Python types as
fields? Hints about different approaches to library implementation are
also welcome. :)
Thanks for you help (and excuse me for my poor english).
Daniele
More information about the Cython-dev
mailing list