[英]How to wrap a C++ functor in Cython
I'm trying to wrap a C++ library in which the logic is implemented as templatized functors in .hpp
files, and I'm struggling to find the right way to expose the C++ functors as Cython/Python functions. 我正在尝试包装一个C ++库,其中逻辑被实现为
.hpp
文件中的模板化.hpp
函数,而我正在努力找到将C ++仿函数公开为Cython / Python函数的正确方法。 How are functors like the one below supposed to be wrapped in Cython? 下面的算符如何被Cython包裹?
I believe this should be possible, at least for template classes and functions, according to the Cython 0.20 docs . 根据Cython 0.20文档 ,我认为这应该是可能的,至少对于模板类和函数而言 。
Note: I think I've figured out how to wrap normal C++ functions—the problem occurs when I'm trying to wrap a templatized functor , ie a template struct
that overloads the ()
operator (making it act like a function when a data type is fixed). 注意:我想我已经弄清楚如何包装普通的C ++函数 - 当我试图包装一个模板化的函子时 ,问题就出现了, 即一个模板
struct
重载了()
运算符(使它在数据时就像一个函数)类型是固定的)。
Disclaimer: I'm a total novice in C++ and very new to Cython so apologies if I'm making obvious mistakes here. 免责声明:我是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
file: 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)
The above just gives a Calling non-function type 'emd_hat_gd_metric[NUM_T]'
error when I try to compile it with cython --cplus wrapper.pyx
. 当我尝试使用
cython --cplus wrapper.pyx
编译它时,上面只给出了一个Calling non-function type 'emd_hat_gd_metric[NUM_T]'
错误。
Here's the full library I'm trying to wrap. 这是我想要包装的完整库。
End goal: to be able to call emd_hat_gd_metric
as a Cython/Python function, with arguments being NumPy arrays. 最终目标:能够将
emd_hat_gd_metric
称为Cython / Python函数,参数为NumPy数组。
I couldn't find a real solution, but here's a workaround (that requires modifying the C++ code): just instantiate the template function with the data type you need in the C++ header, then declare that function normally in your .pyx
file. 我找不到真正的解决方案,但这是一个解决方法(需要修改C ++代码):只需在C ++标头中使用您需要的数据类型实例化模板函数,然后在
.pyx
文件中正常声明该函数。
It's a little unwieldy if you need many different data types, but I only needed double
. 如果你需要许多不同的数据类型,它有点笨拙,但我只需要
double
。 It would also be nicer if it wasn't necessary to modify the external library… but it works. 如果没有必要修改外部库也会更好......但是它有效。
some_library.hpp
file: some_library.hpp
文件中: Instantiate the functor with the data type you need (say, double
): 使用您需要的数据类型(例如,
double
)实例化仿函数:
template<typename T>
struct some_template_functor {
T operator()(T x);
};
// Add this:
some_template_functor<double> some_template_functor_double;
.pyx
file: .pyx
文件中: Declare the function normally (no need for cppclass
): 正常声明函数(不需要
cppclass
):
cdef extern from "path/to/some_library.hpp":
cdef double some_template_functor_double(double x)
Then you can call some_template_functor_double
from within Cython. 然后,你可以调用
some_template_functor_double
从内部用Cython。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.