Cython:如何使用模板?
Cython: How to use templates?
我想对以下模板化 C++ 进行 cythonize class:
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 是额外的模板化 classes 但我不确定是否要在 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)
他们 return 包含 xmin、xmax、ymin、ymax 的元组列表。
我的问题:
在这种情况下使用融合类型是否正确?
如果我获取元组列表,如何在 Cython 代码中将它们转换为 Box[T]/Point[T],而不在 [=41] 中暴露这些 classes =]?得到结果后,我可以将其转换回元组列表并将其发回。即,convert_boxes 的实现应该是什么样的?
感谢您的帮助。
问题 1 - 很遗憾,您不能在那里使用融合类型。 (请参阅之前关于该主题的问题:c++ class in fused type; )。您必须为每个不同的变体创建一个单独的包装器。例如:
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。
我想对以下模板化 C++ 进行 cythonize class:
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 是额外的模板化 classes 但我不确定是否要在 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)
他们 return 包含 xmin、xmax、ymin、ymax 的元组列表。
我的问题:
在这种情况下使用融合类型是否正确?
如果我获取元组列表,如何在 Cython 代码中将它们转换为 Box[T]/Point[T],而不在 [=41] 中暴露这些 classes =]?得到结果后,我可以将其转换回元组列表并将其发回。即,convert_boxes 的实现应该是什么样的?
感谢您的帮助。
问题 1 - 很遗憾,您不能在那里使用融合类型。 (请参阅之前关于该主题的问题:c++ class in fused type;
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。