如果您拥有现代的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
是平凡的,你可以去那里你调用一个方法move
上Peak
而上的向量,为您建造PyPeak
秒。对于这种情况,您在此处移动和复制将等同于`Peak。
如果您不能使用C
11
功能,则需要稍微更改一下接口。不用让C
getPeaks
函数返回向量,而是将一个空的向量引用(由拥有PyPeakVector
)作为输入参数并写入其中。其余的大部分包装都保持不变。