将python对象转换为cython指针

时间:2012-12-02 14:00:22

标签: cython

我正在尝试使用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)

2 个答案:

答案 0 :(得分: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)  

答案 1 :(得分: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)