我正在尝试包装一个C ++库,其中逻辑被实现为.hpp
文件中的模板化仿函数,我正在努力找到将C ++仿函数公开为Cython / Python函数的正确方法。像下面那样的仿函数应该如何用Cython包装?
我认为这应该是可行的,至少对于模板类和函数来说,根据Cython 0.20 docs。
注意:我想我已经弄清楚如何包装普通的C ++函数 - 当我试图包装一个模板化的仿函数时出现问题,即模板struct
,它使()
运算符重载(当数据类型被修复时,它就像一个函数)。
免责声明:我是C ++的新手,也是Cython的新手,如果我在这里犯了明显的错误,请道歉。
#include <vector>
#include "EMD_DEFS.hpp"
#include "flow_utils.hpp"
template<typename NUM_T, FLOW_TYPE_T FLOW_TYPE= NO_FLOW>
struct emd_hat_gd_metric {
NUM_T operator()(const std::vector<NUM_T>& P, const std::vector<NUM_T>& Q,
const std::vector< std::vector<NUM_T> >& C,
NUM_T extra_mass_penalty= -1,
std::vector< std::vector<NUM_T> >* F= NULL);
};
wrapper.pyx
文件:# distutils: language = c++
from libcpp.vector cimport vector
cdef extern from "lib/emd_hat.hpp":
# Apparently `cppclass` is necessary here even though
# `emd_hat_gd_metric` is not a class...?
cdef cppclass emd_hat_gd_metric[NUM_T]:
NUM_T operator()(vector[NUM_T]& P,
vector[NUM_T]& Q,
vector[vector[NUM_T]]& C) except +
cdef class EMD:
cdef emd_hat_gd_metric *__thisptr
def __cinit__(self):
self.__thisptr = new emd_hat_gd_metric()
def __dealloc__(self):
del self.__thisptr
def calculate(self, P, Q, C):
# What goes here? How do I call the functor as a function?
return self.__thisptr(P, Q, C)
当我尝试使用Calling non-function type 'emd_hat_gd_metric[NUM_T]'
进行编译时,上面只会出现cython --cplus wrapper.pyx
错误。
Here's the full library I'm trying to wrap.
结束目标:能够将emd_hat_gd_metric
作为Cython / Python函数调用,参数为NumPy数组。
答案 0 :(得分:2)
我找不到真正的解决方案,但这是一种解决方法(需要修改C ++代码):只需在C ++标头中使用所需的数据类型实例化模板函数,然后在{{{ 1}}文件。
如果您需要许多不同的数据类型,这有点笨拙,但我只需要.pyx
。如果没有必要修改外部库,它也会更好......但是它可以工作。
double
文件中:使用您需要的数据类型(例如,some_library.hpp
)实例化仿函数:
double
template<typename T>
struct some_template_functor {
T operator()(T x);
};
// Add this:
some_template_functor<double> some_template_functor_double;
文件中:正常声明函数(不需要.pyx
):
cppclass
然后你可以在Cython中调用cdef extern from "path/to/some_library.hpp":
cdef double some_template_functor_double(double x)
。