【问题标题】:How do I return wrapped C++ Objects in Cython from another wrapped Object?如何从另一个包装的对象返回 Cython 中的包装 C++ 对象?
【发布时间】:2016-11-11 16:29:28
【问题描述】:

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

cimport cppClassA

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

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

【问题讨论】:

    标签: python c++ cython


    【解决方案1】:

    您的问题并不完全清楚 foo 是通过指针还是值返回(即它是否具有签名 B* foo()B foo())。你必须做什么取决于这一点 - 我已经展示了两者。

    我认为您遇到的问题是PyB__init____cinit__ 方法只能将Python 对象作为参数,因此您无法通过C++ @987654327 @object in。解决方法是创建一个PyB,它要么是空的,要么具有默认的C++ 对象为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&)
    

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

    Python B 持有者 (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 设置为任何值。

    然后是 Python A 持有者 (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,然后使用Bs 移动(或复制)构造函数来创建一个B*

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

    【讨论】:

      猜你喜欢
      • 2018-12-29
      • 1970-01-01
      • 2011-09-02
      • 2018-06-01
      • 2023-03-20
      • 1970-01-01
      • 2023-03-22
      • 2011-02-25
      • 1970-01-01
      相关资源
      最近更新 更多