forward declared structure from ctypes to cython

151 views
Skip to first unread message

Antoine Loriette

unread,
May 24, 2017, 11:26:08 AM5/24/17
to cython-users
question I posted on stackoverflow, but might be a better place here.

The idea is that I use a shared library from ctypes, but there are some functions defined as inline in h files that I still need to compile in order to get access to them in python.
I used a simple Python C extension for that, but it is not super portable across platform and python versions. So I wanted to let Cython do the platform dependant things and use it to plug back in the shared library.

The problem is that I am left having to translate ctypes structure to cython - which I can do by setting all the fields manually. But for some structures, I do not have their definition. So I would like to just use the memory space and send it to the shared library.

I have a C library (called clib with header clib.h) that I call through Ctypes. A function get_struct returns a pointer to a structure Foo that is forward-declared in clib.h and that I can use for other function calls as a pointer (like use_struct(Foo* foo)). I would like to use this pointer to call the same function code in Cython.

Since I do not know the content of the structure, I cannot create a duplicate structure in cython and copy over the values from the ctypes ones. So I would like instead to create a cython pointer to the same memory space in order to call some C code that binds the same API.

The code is roughly doing this.

In clib.h:

typedef struct Foo Foo;
Foo * get_struct();
void use_struct(Foo *)

On the python side with ctypes:

# load clib DLL
clib = ctypes.CDLL('clib.so')

# empty Ctypes declaration
class Foo_ct(ctypes.Structure):
    pass

# get and use the struct
clib.get_struct.restype = ctypes.POINTER(Foo_ct)
foo_ct = clib.get_struct()
clib.use_struct(foo_ct)

# call cython code
bar(foo_ct)

On the Cython side, in cylib.pyx:

cdef extern from "clib.h":
    cdef struct Foo:
        pass

    void use_struct(Foo *)


bar(foo_ct):

    cdef Foo* foo_cy
    foo_cy = <Foo*>&foo_ct  # or something equivalent
    cy_use_struct(foo_cy)

On the Cython side, in cylibc.cpp:

#import "clib.h"

void cy_use_struct(Foo * foo)
{
    use_struct(foo);
}

This does not build and returns errors either Cannot take address of Python variable or assigning to 'PyObject *' (aka '_object *') from incompatible type 'void' on the line foo_cy = <Foo*>&foo_ct.

Any ideas to go forward?


Reply all
Reply to author
Forward
0 new messages