简体   繁体   English

如何在Cython中包装C ++仿函数

[英]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的新手,如果我在这里犯了明显的错误,请道歉。


The functor I'm trying to wrap: 我试图包装的仿函数:

#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);
};

My 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. 如果没有必要修改外部库也会更好......但是它有效。


In the C++ some_library.hpp file: 在C ++ 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;

In the Cython .pyx file: 在Cython .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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM