我想对以下模板化的C ++类进行cython化:
template <typname T>
class Fc2Par
{
public:
Fc2Par(std::string const& par_file)
~Fc2Par()
std::vector<Box<T>> convert_boxes(std::vector<Box<T>> const& boxes) const;
std::vector<Point<T>> convert_points(std::vector<Point<T>> const& points) const;
private:
PartitionMap<T> par_map;
PartitionRTree<T> par_idx;
};
实际上,T只会是[int,double]。 Box / Point是附加的模板类,但我不确定是否要在python中公开它。为了进行cythonize,我有以下内容,但我在某些方面陷入困境。我想我可以使用融合型T?
cimport cython
from libcpp.vector cimport vector
from libcpp.string cimport string
my_fused_type = cython.fused_type(cython.int, cython.double)
cdef extern from 'Fc2Par.h':
cdef cppclass Fc2Par[T]
Fc2Par(string&) except +
vector[Box[T]] convert_boxes(vector[Box[T]]&)
vector[Point[T]] convert_points(vector[Point[T]]&)
cdef class PyFc2Par:
cdef Fc2Par* thisptr <-- should this be Fc2Par[my_fused_type]*?
def __cinit__(self, par_file):
self.thisptr = new Fc2Par[my_fused_type](par_file)
def __dealloc__(self)
del self.thisptr
def convert_boxes(self, boxes)
I'm not sure what to do here?
def convert_points(self, points)
This will be very similar to convert_boxes once I figure that out.
理想情况下,我想在python中使用这样的API:
boxes_int = [(0,0,1,1), (0,0,2,2), ...]
boxes_float = [(0.0,0.0,1.0,1.0), (0.0,0.0,2.0,2.0), ...]
fc2par = PyFc2Par('foo.csv')
converted_int = fc2par.convert_boxes(boxes_int)
converted_float = fc2par.convert_boxes(boxes_float)
它们返回带有xmin,xmax,ymin,ymax的元组列表。
我的问题:
在这种情况下使用融合类型是否正确?
如果我列出元组列表,如何在Cython代码中将它们转换为Box [T] / Point [T]而不在Python中公开这些类?获得结果后,我可以将其转换回元组列表并将其发回。即,convert_boxes实现应该如何?
感谢您的帮助。
答案 0 :(得分:0)
问题1 - 遗憾的是,您无法在那里使用融合类型。 (请参阅有关此主题的先前问题:c++ class in fused type; Cython: templates in python class wrappers)。您必须为每个不同的变体创建单独的包装器。 e.g:
cdef class PyFc2ParInt:
cdef Fc2Par[int]* thisptr
# etc ...
cdef class PyFc2ParDouble:
cdef Fc2Par[double]* thisptr
# etc ...
遗憾的是,这涉及到许多不可避免的代码重复。
问题2.如果convert_points
实质上涉及迭代Python列表创建框,然后迭代向量以创建Python列表,则实现。粗略的轮廓是:
def convert_points(self, points):
cdef vector[Box[double]] v # or vector[Box[int]]
for p in points:
# I've taken a guess at what the Box constructor looks like
v.push_back(Box[double](p[0],p[1],p[2],p[3]))
v = self.thisptr.convert_points(v) # reuse v for the output
# now iterate through the vector and copy out
# I've taken a guess at the interface of Box
output = [ (v[i].left, v[i].right, v[i].top, v[i].bottom)
for i in range(v.size()) ]
return output
请注意,您需要告诉Cython关于Box
(cdef extern from ...
),即使您没有将其公开给Python。