Wil*_*ill 5 c++ python functor cython
我正在尝试包装一个C++库,其中逻辑被实现为.hpp文件中模板化的函子,我正在努力找到将C++函子暴露为Cython/Python函数的正确方法.下面的算符如何被Cython包裹?
根据Cython 0.20文档,我认为这应该是可能的,至少对于模板类和函数而言.
注意:我想我已经弄清楚了如何包装普通的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);
};
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
上面只是Calling non-function type 'emd_hat_gd_metric[NUM_T]'在我尝试编译时出错cython --cplus wrapper.pyx.
最终目标:能够emd_hat_gd_metric作为Cython/Python函数调用,参数为NumPy数组.
我找不到真正的解决方案,但这里有一个解决方法(需要修改 C++ 代码):只需在 C++ 标头中使用所需的数据类型实例化模板函数,然后在文件中正常声明该函数即可.pyx。
如果您需要许多不同的数据类型,这有点笨拙,但我只需要double. 如果不需要修改外部库\xe2\x80\xa6但它可以工作,那就更好了。
some_library.hpp文件中:使用您需要的数据类型实例化函子(例如double):
template<typename T>\nstruct some_template_functor {\n T operator()(T x);\n};\n\n// Add this:\nsome_template_functor<double> some_template_functor_double;\nRun Code Online (Sandbox Code Playgroud)\n\n.pyx文件中:正常声明函数(不需要cppclass):
cdef extern from "path/to/some_library.hpp":\n cdef double some_template_functor_double(double x)\nRun Code Online (Sandbox Code Playgroud)\n\n然后您可以some_template_functor_double从 Cython 内部调用。