簡體   English   中英

將Cython中的C結構包裝/轉換為Python類

[英]Wrapping/Casting C struct in Cython to Python class

我剛剛開始熟悉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 <Test?>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函數(例如構造函數)。 所以你也需要一個工廠功能。 這是一個例子:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM