8

我正在尝试使用 cython 将 c++ 类公开给 python。我在 *.pxd 文件中编写了它们的定义,并在 *.pyx 文件中实现了一个包装器。但是我试图将函数指针传递给扩展类型时遇到了困难。这是简化的示例。

foo.pyx

from c_foo cimport cFoo
cdef class Foo:
    cdef cFoo* _impl

c_foo_holder.pxd

cdef extern from "FooHolder.h":
    cdef cppclass cFooHolder:
        cFooHolder(cFoo* foo)    

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    

但在最后一行我得到错误“ 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)
4

2 回答 2

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

foo.pyx

from c_foo cimport cFoo
cdef class Foo:
    # methods implementation

c_foo_holder.pxd

cdef extern from "FooHolder.h":
    cdef cppclass cFooHolder:
        cFooHolder(cFoo* foo)    

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)  
于 2012-12-05T16:49:37.810 回答
0

__init__构造函数只能接受纯 Python 对象,也有__cinit__但只能接受 C 原始类型。

当您将 Foo 传递给__init__它时,它看不到_impl成员,只能看到 python 类型的成员。

解决方案是cFoo*显式传递给Init()模拟构造函数的方法:

cdef class FooHolder:
    cdef cFooHolder* _impl
    cdef void Init(self, cFoo* foo_impl):
        self._impl = new cFooHolder(foo_impl)

这样称呼它:

fooHolder = new FooHolder()
fooHolder.Init(foo._impl)
于 2012-12-03T15:43:01.840 回答