如何从另一个包装的Object返回Cython中的包装C ++对象?

时间:2016-11-11 16:29:29

标签: python c++ cython

我用Cython包装了C ++ Classes。现在我有以下问题:类A有一个方法foo(),它返回一个B类实例。两个都是C ++类。两者都用Cython包装到Class PyA和PyB。我想以某种方式使用户可以访问方法foo(),用户调用PyA_object.foo()并获取PyB_object。我该如何实现该方法?

cimport cppClassA

cdef class A:
    cdef cppClassA.A *ptr
    ...
def foo():
    return self.ptr.foo()

这样我返回直接C ++类B,但我想返回一个PyB。因此我需要创建一个PyB对象,但是如何构造PyB的 cinit ()方法呢?如何将self.ptr.foo()中返回的对象提供给新的PyB对象并返回呢?

1 个答案:

答案 0 :(得分:0)

根据您的问题,foo是否通过指针或值返回(即它是否具有签名B* foo()B foo())并不完全清楚。你要做的事情取决于这一点 - 我已经证明了这两点。

我认为您遇到的问题是__init____cinit__ PyB方法只能将Python对象作为参数,因此您可以使用#{1}}或B方法作为参数。我无法传递C ++ PyB对象。解决方案是创建一个空的ptr或默认的C ++对象为cdef extern from "somefile.hpp": cdef cppclass A: B foo1() B* foo2() cdef cppclass B: # only need to provide these for foo1_alternative B() B(const B&) ,然后替换它。

C ++代码的包装看起来像这样

foo

请注意,我提供了两个版本的foo1 - foo2,它们按值返回,B返回指针。

Python PyB持有人(cdef class PyB: cdef B* ptr def __cinit__(self,make_ptr=True): if make_ptr: self.ptr = new B() else: self.ptr = NULL def __dealloc__(self): del self.ptr )看起来像

make_ptr

我提供了一个可选的False参数,您可以将其设置为self.ptr,以避免将A设置为任何内容。

然后

Python PyA持有人(cdef class PyA: cdef A* ptr # code goes here def foo1(self): cdef PyB val = PyB() val.ptr[0] = self.ptr.foo1() # use move (or copy) assignment operator def foo1_alternative(self): cdef PyB val = PyB(make_ptr=False) val.ptr = new B(self.ptr.foo1()) # use move (or copy) constructor def foo2(self): cdef PyB val = PyB(make_ptr=False) val.ptr = self.ptr.foo2()

foo2

对于返回指针的PyB,您只需创建一个空的Foo*并将self.ptr分配给foo1。对于PyB,您有两个选项,其中一个选项涉及使用移动(或复制)赋值运算符创建带有内容的PyB来复制数据。第二个选项涉及创建一个空的B,然后使用B*的移动(或复制)构造函数来创建form1.Action = "myURL";

如果可以的话,你最好使用移动构造函数而不是复制构造函数,但是你不需要告诉Cython(C ++会自动选择正确的)。