重要更新:可重复的示例here

我在documentation中有类似的代码,因此该类是从指针创建的。当类定义和类实例创建都在同一文件中时,它可以完美地工作。

main.pyx:

cdef some_type * ptr_to_wrapped_type = <some_type *>malloc(sizeof(some_type))

#next part from documentation
cdef class WrapperClass:
    """A wrapper class for a C/C++ data structure"""
    cdef my_c_struct *_ptr
    cdef bint ptr_owner

    @staticmethod
    cdef WrapperClass from_ptr(my_c_struct *_ptr, bint owner=False):
        """Factory function to create WrapperClass objects from
        given my_c_struct pointer.
        Setting ``owner`` flag to ``True`` causes
        the extension type to ``free`` the structure pointed to by ``_ptr``
        when the wrapper object is deallocated."""
        # Call to __new__ bypasses __init__ constructor
        cdef WrapperClass wrapper = WrapperClass.__new__(WrapperClass)
        wrapper._ptr = _ptr
        wrapper.ptr_owner = owner
        return wrapper
...

data = WrapperClass.from_ptr(ptr_to_wrapped_type, owner=True)


我想要的是将类定义移动到单独的文件中,并将其导入main中。这在docs中也有描述,这就是我所拥有的:

wrapper.pxd:

# Example C struct
ctypedef struct my_c_struct:
    int a
    int b

cdef class WrapperClass:
    """A wrapper class for a C/C++ data structure"""
    cdef my_c_struct *_ptr
    cdef bint ptr_owner


wrapper.pyx(docs中的类定义):

from libc.stdlib cimport malloc, free

cdef class WrapperClass:
    """A wrapper class for a C/C++ data structure"""
    cdef my_c_struct *_ptr
    cdef bint ptr_owner

    def __cinit__(self):
        self.ptr_owner = False

    def __dealloc__(self):
        # De-allocate if not null and flag is set
        if self._ptr is not NULL and self.ptr_owner is True:
            free(self._ptr)
            self._ptr = NULL

    @staticmethod
    cdef WrapperClass from_ptr(my_c_struct *_ptr, bint owner):
        """Factory function to create WrapperClass objects from
        given my_c_struct pointer.
        Setting ``owner`` flag to ``True`` causes
        the extension type to ``free`` the structure pointed to by ``_ptr``
        when the wrapper object is deallocated."""
        # Call to __new__ bypasses __init__ constructor
        cdef WrapperClass wrapper = WrapperClass.__new__(WrapperClass)
        wrapper._ptr = _ptr
        wrapper.ptr_owner = owner
        return wrapper
...


最后在main.pyx中:

cdef some_type * ptr_to_wrapped_type = <some_type *>malloc(sizeof(some_type))

from wrapper cimport WrapperClass

data = WrapperClass.from_ptr(ptr_to_wrapped_type, owner=True)


不幸的是,在编译时出现错误:

data = WrapperClass.from_ptr(ptr_to_wrapped_type, owner=True)
                            ^
------------------------------------------------------------

Cannot convert 'some_type *' to Python object


怎么了?

最佳答案

在github上您无法使用的示例中,当您使用.pxd(头文件)文件时,所有cdefcpdef函数也需要在此列出(没有实现/函数主体)。这样,当您将类cimport放入其他.pyx模块时,就可以访问这些功能。这就是为什么您的main.pyx找不到WrapperClassfrom_ptr函数的原因。

关于python - 在没有导入的同一个类没有问题的情况下将指针传递给导入的扩展类型方法时出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57185219/

10-10 16:09