您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何在不复制对象的情况下公开将C ++对象返回给Python的函数?

如何在不复制对象的情况下公开将C ++对象返回给Python的函数?

如果您拥有现代的C ++编译器并且可以使用右值引用,请移动构造函数和std :: move,这非常简单。我认为最简单的方法是为向量创建Cython包装器,然后使用move构造函数来掌握向量的内容

显示的所有代码都在peak_detection_.pyx中。

先包好std::move。为了简单起见,我只包装了我们想要的一种情况(vector<Peak>),而不是弄乱模板。

cdef extern from "<utility>":
    vector[Peak]&& move(vector[Peak]&&) # just define for peak rather than anything else

其次,创建向量包装器类。这定义了像列表一样访问它所必需的Python函数。它还定义了一个函数调用移动分配运算符

cdef class PyPeakVector:
    cdef vector[Peak] vec

    cdef move_from(self, vector[Peak]&& move_this):
        self.vec = move(move_this)

    def __getitem__(self,idx):
        return PyPeak2(self,idx)

    def __len__(self):
        return self.vec.size()

然后定义包装的类Peak。这与您的其他类稍有不同,因为它不拥有Peak包装的内容(向量包含)。否则,大多数功能保持不变

cdef class PyPeak2:
    cdef int idx
    cdef PyPeakVector vector # keep this alive, since it owns the peak rather that PyPeak2

    def __cinit__(self,PyPeakVector vec,idx):
        self.vector = vec
        self.idx = idx

    cdef Peak* getthisptr(self):
        # lookup the pointer each time - it isn't generally safe
        # to store pointers incase the vector is resized
        return &self.vector.vec[self.idx]

    # rest of functions as is

    # don't define a destructor since we don't own the Peak

最后实施 getPeaks()

cdef class PyPeakDetection:
    # ...    
    def getPeaks(self, data):
        cdef Peak peak
        cdef PyPeak new_peak
        cdef vector[Peak] peaks = self.thisptr.getPeaks(data)

        retval = PyPeakVector()
        retval.move_from(move(peaks))

        return retval

如果Peak是平凡的,你可以去那里你调用一个方法movePeak而上的向量,为您建造PyPeak秒。对于这种情况,您在此处移动和复制将等同于`Peak。

如果您不能使用C 11 功能,则需要稍微更改一下接口。不用让C getPeaks函数返回向量,而是将一个空的向量引用(由拥有PyPeakVector)作为输入参数并写入其中。其余的大部分包装都保持不变。

python 2022/1/1 18:48:16 有341人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶