将Cython中的C结构包装/转换为Python类

我刚刚开始熟悉Cython,试图将一些C语言结构包装到Python方法和类中。 我真正不了解的是如何从(初始化的)C结构转换到相应的Python类应该是有效的。 我在这里缺少什么:

来自C头文件的片段:

struct test_struct { int _something; complex_struct* _another; }; typedef struct test_struct test; test *test_new(void); int some_method(test **n, int irrelevant); 

来自我.pxd的相应片段:

 cdef struct test_struct: pass ctypedef test_struct test test* test_new() int some_method(test **n, int irrelevant) 

我的.pyx:

 def do_something(int irrelevant): cdef test* t = test_new() ret = some_method(&t, irrelevant) # Here comes the problem... return t cdef class Test: cdef test* _t # cinit here and some methods here. No members except _t 

返回声明的一切正常。 我在ret等中获得了正确的值。但是return语句中的强制转换似乎不正确或者缺少更多信息。 当发出t = do_something(42) Python段错误时。

段错误本身并没有帮助:

 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7a9e74b in internal_print () from /usr/lib/libpython2.7.so.1.0 (gdb) bt #0 0x00007ffff7a9e74b in internal_print () from /usr/lib/libpython2.7.so.1.0 #1 0x00007ffff7a81adb in PyFile_WriteObject () from /usr/lib/libpython2.7.so.1.0 #2 0x00007ffff7b19acb in sys_displayhook () from /usr/lib/libpython2.7.so.1.0 #3 0x00007ffff7a64c23 in PyObject_Call () from /usr/lib/libpython2.7.so.1.0 #4 0x00007ffff7af2ff7 in PyEval_CallObjectWithKeywords () from /usr/lib/libpython2.7.so.1.0 #5 0x00007ffff7af6f3b in PyEval_EvalFrameEx () from /usr/lib/libpython2.7.so.1.0 #6 0x00007ffff7af91b0 in PyEval_EvalCodeEx () from /usr/lib/libpython2.7.so.1.0 #7 0x00007ffff7af92b2 in PyEval_EvalCode () from /usr/lib/libpython2.7.so.1.0 #8 0x00007ffff7b11f9f in run_mod () from /usr/lib/libpython2.7.so.1.0 #9 0x00007ffff7b13ec0 in PyRun_InteractiveOneFlags () from /usr/lib/libpython2.7.so.1.0 #10 0x00007ffff7b140ae in PyRun_InteractiveLoopFlags () from /usr/lib/libpython2.7.so.1.0 #11 0x00007ffff7b1470e in PyRun_AnyFileExFlags () from /usr/lib/libpython2.7.so.1.0 #12 0x00007ffff7b24bcf in Py_Main () from /usr/lib/libpython2.7.so.1.0 #13 0x00007ffff746f000 in __libc_start_main () from /usr/lib/libc.so.6 #14 0x000000000040073e in _start () 

如您所见, do_something方法应返回Test类型的Python对象。 我需要添加什么才能使演员成功? 我是否需要手动将结构映射到Python类? 我可以使用一些Cython魔法吗?

您需要将Test为围绕C类型的实际包装器。 但是你也不能将C参数传递给Python函数(例如构造函数)。 所以你也需要一个工厂function。 这是一个例子:

 cdef class Test: cdef test* _t def __cinit__(self): self._t = NULL def _setup(self, test* t): self._t = t return self property something: def __get__(self): return self._t._something def __set__(self, int val): self._t._something = val cdef Test_create(test* t): return Test()._setup(t) 

然后在do_something()

 return Test_create(t)