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

私は解決策を見つけました。foo._implは実際にはcFoo*インスタンスであることをcythonに伝える必要があります。これは、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 に答える