将python对象转换为cython指针

Dik*_*rAz 8 cython

我正在尝试使用cython将c ++类暴露给python.我在*.pxd文件中编写了他们的定义,并在*.pyx文件中实现了一个包装器.但我试图传递给扩展类型的函数指针.这是简化的例子.

foo.pyx

from c_foo cimport cFoo
cdef class Foo:
    cdef cFoo* _impl
Run Code Online (Sandbox Code Playgroud)

c_foo_holder.pxd

cdef extern from "FooHolder.h":
    cdef cppclass cFooHolder:
        cFooHolder(cFoo* foo)    
Run Code Online (Sandbox Code Playgroud)

foo_holder.pyx

from c_foo_holder cimport cFooHolder
from c_foo cimport cFoo

cdef class FooHolder:
    cdef cFooHolder* _impl
    def __init__(self, foo):
        self._impl = new cFooHolder(<cFoo*>(foo._impl)) # error here    
Run Code Online (Sandbox Code Playgroud)

但是在最后一行我得到错误" Python对象不能被强制转换为原始类型的指针 ".我还尝试了其他几种方法,但没有任何效果:

# error: 'Foo' is not a type identifier 
from foo import Foo
def __init__(self, Foo foo):
    self._impl = new cFooHolder(foo._impl)

# error: 'Foo' is not a type identifier 
def __init__(self, foo):
   self._impl = new cFooHolder(<Foo>(foo)._impl)
Run Code Online (Sandbox Code Playgroud)

Dik*_*rAz 3

我找到了解决方案。您必须告诉 cython foo._impl 实际上是 cFoo* 实例。这可以通过提供 Foo 定义(例如在 foo.pxd 中)来实现。之后,您可以将 python 对象强制转换为 Foo,并且 cython 将知道其 _impl 字段的类型为 cFoo*。

foo.pxd

from c_foo cimport cFoo
cdef class Foo:
    cdef cFoo* _impl
Run Code Online (Sandbox Code Playgroud)

foo.pyx

from c_foo cimport cFoo
cdef class Foo:
    # methods implementation
Run Code Online (Sandbox Code Playgroud)

c_foo_holder.pxd

cdef extern from "FooHolder.h":
    cdef cppclass cFooHolder:
        cFooHolder(cFoo* foo)    
Run Code Online (Sandbox Code Playgroud)

foo_holder.pyx

from c_foo_holder cimport cFooHolder
from c_foo cimport cFoo
from foo cimport Foo

cdef class FooHolder:
    cdef cFooHolder* _impl
    def __init__(self, foo):
        self._impl = new cFooHolder((<Foo?>foo)._impl)  
Run Code Online (Sandbox Code Playgroud)