Cython:模块拆分后无法将指针转换为Python对象
问题:Cython:模块拆分后无法将指针转换为Python对象,python,c,cython,Python,C,Cython,问题: Error compiling Cython file: ------------------------------------------------------------ ... cpdef Py_GetRemoteDevice(PyChannel Chan): ret_val = mod_one.PyRemoteDevice() cdef core.RemoteDevice * tmp with nogil: tmp = core.Ge
Error compiling Cython file:
------------------------------------------------------------
...
cpdef Py_GetRemoteDevice(PyChannel Chan):
ret_val = mod_one.PyRemoteDevice()
cdef core.RemoteDevice * tmp
with nogil:
tmp = core.GetRemoteDevice(Chan.__instance)
ret_val.__set_ptr(tmp)
^
------------------------------------------------------------
core/mod_two.pyx:11589:25: Cannot convert 'RemoteDevice *' to Python object
背景:
我有一个相当大的C库,我正在用Cython包装它。起初我
所有内容都包含在两个文件中,core.pyx和core.pxd。但是,
生成的core.c文件越大。
250万行和计数。编译时间和内存使用率变得越来越高
笨重的
我决定将内容拆分为多个.pyx文件。那是过去的事情
工作停止了
免责声明:
请记住,我已经大大简化了这个问题。
包装的库有点大并且是专有的
详细信息:core.pxd-包含C库中所有必需的组件
我正在包装。还有一个简单的Void*包装器类声明
cdef class Void:
cdef void *__void
cdef __set_ptr(self, void *ptr)
cdef extern from "core.h":
ctypedef unsigned char U8
ctypedef unsigned int U32
void OS_MemSet(U8 *dest, U8 byte, U32 len) nogil
cdef extern from "mod_one.h":
cdef struct _RemoteDevice
ctypedef _RemoteDevice RemoteDevice
cdef extern from "mod_two.h":
cdef struct _Channel
ctypedef _Channel Channel
pyx-这里不需要太多,实际上它只是
Void*包装器的实现
cdef class Void:
cdef __set_ptr(self, void *ptr):
self.__void = ptr
mod_one.pxd-声明RemoteDevice C结构的包装器类
cimport core
cdef class PyRemoteDevice:
cdef core.RemoteDevice *__instance
cdef __set_ptr(self, core.RemoteDevice *ptr)
mod_one.pyx-定义RemoteDevice包装类。注意
__set_ptr函数,它是cdef'd并接受远程设备*
from cpython.mem cimport PyMem_Malloc, PyMem_Free
import core
cimport core
cdef class PyRemoteDevice:
def __cinit__(self):
self.__instance = <core.RemoteDevice *>PyMem_Malloc(sizeof(core.RemoteDevice))
def __init__(self):
core.OS_MemSet(<core.U8 *>self.__instance, <core.U8>0, sizeof(core.RemoteDevice))
cdef __set_ptr(self, core.RemoteDevice *ptr):
self.__instance = ptr
def __dealloc__(self):
if self.__instance is not NULL:
PyMem_Free(self.__instance)
self.__instance = NULL
mod_two.pyx-定义通道包装器类,并声明
Py_GetRemoteDevice函数,它包装了GetRemoteDevice函数
来自C库
from cpython.mem cimport PyMem_Malloc, PyMem_Free import core cimport core import mod_one cimport mod_one
cdef class PyChannel:
def __cinit__(self):
self.__instance = <core.Channel *>PyMem_Malloc(sizeof(core.Channel))
def __init__(self):
core.OS_MemSet(<core.U8 *>self.__instance, <core.U8>0, sizeof(core.Channel))
cdef __set_ptr(self, core.Channel *ptr):
self.__instance = ptr
def __dealloc__(self):
if self.__instance is not NULL:
PyMem_Free(self.__instance)
self.__instance = NULL
cpdef Py_GetRemoteDevice(PyChannel Chan):
ret_val = mod_one.PyRemoteDevice()
cdef core.RemoteDevice * tmp
with nogil:
tmp = core.GetRemoteDevice(Chan.__instance)
ret_val.__set_ptr(tmp)
return ret_val
我有点困惑,因为当我把所有的东西都放在一个盒子里的时候,这种方法就行了
模块。我可以看到的一个区别是,我所有的包装器类都是完全定义的
因为我不需要在模块之间共享它们。现在
我需要共享它们,所以我将它们拆分为.pyx和.pxd文件
谁能给我指出正确的方向吗?我搜索了Cython文档和谷歌
但到目前为止,我还没有找到任何答案
谢谢,如果需要更多信息,请告诉我 访问扩展类型上的c级函数需要cython知道确切的类型,否则它将被视为通用Python对象。因此需要这样的类型注释
cdef mod_one.PyRemoteDevice ret_val = ...
看来你需要在
ret_val
?@chrisb上做一个类型注释,我想知道,但我一直没能让它工作。可能是因为我不确定它应该是什么样子。我尝试了mod_one.PyRemoteDevice ret_val=mod_one.PyRemoteDevice(),但没有成功。不过我还是要再试一次,只是为了确定。好吧,@chrisb,你说得对。当我键入最后一条评论时,我意识到我的错误。我需要cdef
放在我上一次发布的内容前面,所以它应该是cdef mod_one.PyRemoteDevice ret_val=mod_one.PyRemoteDevice()
。我觉得有点傻!如果你把你的评论变成回答,我会接受的。
Error compiling Cython file:
------------------------------------------------------------
...
cpdef Py_GetRemoteDevice(PyChannel Chan):
ret_val = mod_one.PyRemoteDevice()
cdef core.RemoteDevice * tmp
with nogil:
tmp = core.GetRemoteDevice(Chan.__instance)
ret_val.__set_ptr(tmp)
^
------------------------------------------------------------
core/mod_two.pyx:11589:25: Cannot convert 'RemoteDevice *' to Python object
cdef mod_one.PyRemoteDevice ret_val = ...