我试图在cython中包装以下用C ++编写的声明:
template<typename T, double (*distance)(const DataPoint&, const DataPoint&)>
class VpTree
{...}
我在C ++中也有以下定义:
inline double euclidean_distance(const DataPoint &t1, const DataPoint &t2) {...}
,我正在尝试将其包装在cython中。这是我根据以下文档提出的:
cdef extern from "vptree.h":
# declaration of DataPoint omitted here
cdef inline double euclidean_distance(DataPoint&, DataPoint&)
cdef cppclass VpTree[T, F]: # F is almost certainly wrong
...
并为此构建一个包装器:
cdef class VPTree:
cdef VpTree[DataPoint, euclidean_distance] tree
def __cinit__(self):
self.tree = VpTree[DataPoint, euclidean_distance]()
不幸的是,这导致以下错误:
------------------------------------------------------------
cdef class VPTree:
cdef VpTree[DataPoint, euclidean_distance] tree
^
------------------------------------------------------------
unknown type in template argument
------------------------------------------------------------
cdef class VPTree:
cdef VpTree[DataPoint, euclidean_distance] tree
def __cinit__(self):
self.tree = VpTree[DataPoint, euclidean_distance]()
^
------------------------------------------------------------
unknown type in template argument
我怀疑问题出在定义的F
部分,我已经尝试了各种方法来代替它,例如double(*)(DataPoint&, DataPoint&)
,但这显然会导致语法错误。
答案 0 :(得分:2)
据我所知,Cython不直接支持非类型模板参数(即函数指针是什么)(尽管我可能错过了备忘录),但是有一个众所周知的 cname-hack 以实现目标。
在这里,举一个简单得多的例子:
%%cython --cplus
cdef extern from *:
"""
template<int val>
int fun(){return val;}
"""
int fun[T]()
即int
值作为模板参数。
现在我们面临一个难题:Cython期望T为类型,而g ++(或其他编译器)期望为整数值-这是 cname-hack 的代名词:
%%cython --cplus
...
cdef extern from *:
ctypedef int val2 "2"
def doit():
return fun[val2]()
Cython认为val2
是一种类型(int
的别名),但是在生成的c ++代码(2
)中将其替换为fun<2>()
,因此是c ++编译器会看到一个预期的整数值(在这种情况下为2
。
对于您的情况,这意味着添加:
%%cython --cplus
...
cdef extern from *:
ctypedef int euclidean_distance_t "euclidean_distance"
cdef class VPTree:
cdef VpTree[DataPoint, euclidean_distance_t] tree
def __cinit__(self):
self.tree = VpTree[DataPoint, euclidean_distance_t]()
如果您在Cython代码中的其他任何地方都没有使用“ euclidean_distance”,则实际上根本不需要包装它。