cython 将 void* 转换回 Python 对象
在尝试把 void* 转换回 Python 对象时遇到了错误信息。
根据这篇文章 将 Python 对象转换为 C 的 void 类型,这个转换应该是很简单的。
struct _node {
void * data;
} node;
cpdef match(self, path):
m = cpyr3.r3_tree_match(self.root, path, NULL)
if m:
return <object>m.data
错误信息:
Error compiling Cython file:
------------------------------------------------------------
...
cpdef match(self, path):
m = cpyr3.r3_tree_match(self.root, path, NULL)
if m:
return <object>m.data
^
------------------------------------------------------------
cpyr3.pyx:18:28: Cannot convert 'node *' to Python object
我测试了几种方法:
1.
Error compiling Cython file:
------------------------------------------------------------
...
cpyr3.r3_tree_compile(self.root, NULL)
cpdef match(self, path):
m = cpyr3.r3_tree_match(self.root, path, NULL)
if m:
return <object>(m.data[0])
^
------------------------------------------------------------
cpyr3.pyx:17:29: Cannot convert 'node *' to Python object
2.
这个方法可以通过编译,但在运行时会抛出异常。
Traceback (most recent call last):
File "test.py", line 22, in <module>
print run(r)
File "test.py", line 13, in run
return r.match('/foo/bar')
File "cpyr3.pyx", line 14, in pyr3.R3Tree.match (cpyr3.c:1243)
cpdef match(self, path):
File "cpyr3.pyx", line 17, in pyr3.R3Tree.match (cpyr3.c:1186)
return <object>(m[0].data[0])
AttributeError: 'dict' object has no attribute 'data'
这个字典是从哪里来的?
编辑2:重现问题(详细信息):
源代码库: https://github.com/lucemia/pyr3/tree/cython
git clone https://github.com/lucemia/pyr3/ -b cython
cd pyr3
rm cpyr3.c
rm pyr3.c
git submodule init; git submodule update;
cd r3
./autogen.sh
./configure
cd ..
python setup_cython.py build_ext --inplace
编辑3:
将 cpyr3.pxd 文件中的内容从
cdef extern from "r3.h":
ctypedef struct node:
pass
改为
cdef extern from "r3.h":
ctypedef struct node:
void *data
这样就解决了问题!
1 个回答
2
我测试了
cdef struct _node:
void * data
ctypedef _node node
cpdef pack_unpack():
cdef node my_node = node(<void *>"some object")
# This is what should be returned
cdef node *m = &my_node
return <object>m.data
和
import pyximport
pyximport.install()
import c_unpacker
print(c_unpacker.pack_unpack())
结果完全没问题。
所以我认为可能是其他地方出了问题。如果能提供一个简单的可运行示例让我测试一下,那就更好了。
这里有三个可能的错误需要检查:
m
没有类型或者类型不正确self.root
或path
类型不对_node
类型不对。例如,使用cdef struct _node: pass
时,我得到的结果是Error compiling Cython file: ------------------------------------------------------------ ... cpdef pack_unpack(): cdef node my_node = node(<void *>"some object") # This is what should be returned cdef node *m = &my_node return <object>m.data ^ ------------------------------------------------------------ c_unpacker.pyx:10:20: Cannot convert 'node *' to Python object
这是因为
m
根据 Cython 看到的错误定义没有data
这个属性。在这种情况下,Cython 默认会将其转换为 Python 类型。
在编译的过程中,我发现你有
cdef extern from "r3.h":
ctypedef struct node:
pass
这是我列表上的第三点。你应该把它改成
cdef extern from "r3.h":
ctypedef struct node:
void *data
这样就能消除那个错误。