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 = ...