Cython访问结构体指针报错:Storing unsafe C derivative of temporary Python reference
解决Cython访问C结构体指针成员的编译错误
让我来帮你拆解这个问题的根源,然后一步步修复它:
错误原因
你遇到的两个编译错误,本质都是Cython没把ptr_list当成真正的C结构体来处理:
- 在你的
.pxd文件里,你定义了包含_heap_ptr的_list结构体,但又单独声明了一个空的ptr_list结构体(ctypedef struct ptr_list: pass)。Cython完全不知道这两个结构体之间有什么关系,所以当你访问basic_list._heap_ptr时,它会误以为basic_list是个Python对象,而非C结构体实例——这就解释了为什么会报错"Cannot convert Python object to 'int *'"。 - 另外,
_heap_ptr是void*类型,Cython不会自动帮你把void*转换成int*,必须显式做类型转换,这也是错误的诱因之一。
修复方案
第一步:修正.pxd的结构体声明
首先要让Cython知道ptr_list和_heap_ptr的关联,这取决于你的C头文件里ptr_list的实际定义,分两种情况:
情况1:ptr_list是_list的直接别名
如果你的C代码里是这么定义的:
typedef struct _list { void* _heap_ptr; // 其他成员 } ptr_list;
那直接把.pxd里的结构体声明合并,明确定义ptr_list的内部成员:
cdef extern from "src/list.h": ctypedef struct ptr_list: void* _heap_ptr # 直接在这里声明结构体成员 ptr_list create_list_size(size_t size, int length) list_destroy(ptr_list this_list) void* list_at_ptr(ptr_list this_list, int index) list_add_ptr(ptr_list this_list, void* value)
情况2:ptr_list是指向_list的指针
如果你的C代码里ptr_list是指针类型(比如typedef struct _list* ptr_list;),那要在.pxd里把它声明为指针:
cdef extern from "src/list.h": ctypedef struct _list: void* _heap_ptr ctypedef _list* ptr_list # 明确ptr_list是_list的指针类型 ptr_list create_list_size(size_t size, int length) list_destroy(ptr_list this_list) void* list_at_ptr(ptr_list this_list, int index) list_add_ptr(ptr_list this_list, void* value)
这种情况下,访问成员要改用->,比如basic_list->_heap_ptr。
第二步:给指针做显式类型转换
因为_heap_ptr是void*,必须显式转换成int*才能赋值给arr,修改你的.pyx代码:
# 对应情况1(ptr_list是结构体) arr = <int*>basic_list._heap_ptr # 对应情况2(ptr_list是指针) arr = <int*>basic_list->_heap_ptr
修正后的完整.pyx示例(情况1)
cimport src.clist as l def main(): cdef l.ptr_list basic_list cdef int i = 42 basic_list = l.create_list_size(sizeof(i), 100) l.list_add_ptr(basic_list, &i) cdef int* arr arr = <int*>basic_list._heap_ptr # 显式转换void*到int* for i in range(1): print(arr[i])
这样修改后,Cython就能正确识别ptr_list是C结构体,顺利访问_heap_ptr成员,编译错误也就解决了。
内容的提问来源于stack exchange,提问作者The Unfun Cat
相关产品推荐
相关产品推荐

