如何使用Cython将python函数作为参数传递给c++函数
How to pass python function as an argument to c++ function using Cython
以下是我的设置:我有下一个c++类,我想把它包装起来:
// Foo.h
class Foo
{
public:
typedef int MyType;
typedef int ArgType1;
typedef int ArgType2;
...
typedef MyType (*FooFunction) (ArgType1 a, ArgType2 b);
...
void setFooFunction(FooFunction f);
在c++中使用该类的示例:
#include "Foo.h"
...
int fooFun(int a, int b)
{
if (a > b) return a;
else return b;
}
...
int main(int argc, char **argv)
{
...
fooObj->setFooFunction(&fooFun);
...
}
Cython包装:
# .pyx
cdef extern from "Foo.h":
cdef cppclass Foo:
void setFooFunction(int *) except +
def bar(fooFun):
...
fooobj.setFooFunction(fooFun)
...
我希望能够这样做:
# python file
...
def pyfun(x, y):
return x + y
...
def main():
bar(pyfun)
我对Cython并不完全熟悉,但是我已经尝试了一些魔法,但它不起作用:
# .pyx
cdef extern from "Foo.h":
cdef cppclass Foo:
void setFooFunction(int *) except +
ctypedef int (*myFun) (int, int)
def bar(fooFun):
cdef myFun funpointer
funpointer = (<myFun*><size_t>id(smoothfun))[0]
...
fooobj.setFooFunction(<int*>fooFun)
...
有可能这样做吗?
你不能轻易做到:c++函数指针只是存储该函数代码开始的内存位置(或类似的东西,具体实现),而Python函数是一个完整的Python对象,带有存储字节码(可能是未编译的Python代码),文档字符串和其他一些位的字典。它也不是机器可以自己运行的形式-它需要Python解释器来处理字节码。没有一种方法可以将所有这些存储在c++函数指针中。
你可能能做的是使用c++ 11 std::function
。这可以像函数指针一样使用,并且可以接受任何可调用对象(任何定义operator()
的对象)。这个想法是,你的类存储一个std::function
而不是一个函数指针。
#include <functional> // for std::function
class Foo {
private:
std::function<int(int,int)> stored_function;
public:
void setFooFunction(std::function<int(int,int)> f) {
stored_function = f;
}
void doSomething() {
// call it like this
int result = stored_function(1,2);
}
};
然后传递给setFooFunction
一个c++类,该类存储PyObject* (Python函数的),并定义operator()
来调用Python。
如果你不想自己编写c++类,boost::python::object
类(http://www.boost.org/doc/libs/1_58_0/libs/python/doc/v2/object.html#object_operators-spec)有你需要的特性。你可以很容易地从Cython
from cpython.ref cimport PyObject
cdef PyObject* pyob_ptr = <PyObject*>some_function
并将其转换为boost c++类也非常简单(http://www.boost.org/doc/libs/1_58_0/libs/python/doc/tutorial/doc/html/python/object.html#python.creating_python_object)
boost::python::object o(boost::python::handle<>(boost::python::borrowed(pyobj_ptr)));
由于o
是可调用的,你应该能够直接在std::function
Foo foo; // a foo object
foo.setFooFunction(o); // pass it the boost::python::object
(显然这里缺少很多细节,但希望这个广泛的方法会有用!)
- 如何在C++中将迭代器作为函数参数传递
- 为什么我不能将引用作为 std::async 的函数参数传递
- 节点插件 API 将数组作为函数参数传递
- 将字符串数组作为函数参数传递
- 如何通过 C++ 中的函数参数传递初始值设定项列表的固定大小的初始值设定项列表?
- 我可以动态创建新地图并作为函数参数传递吗?
- 将任意模板向量作为函数参数C++传递
- 将函数指针作为函数参数传递的目的
- C++:通过函数参数传递的值给出不同的结果
- 当数组大小在C++中未知时,如何在运行时将对字符串数组的引用作为函数参数传递?
- 通过宏将函数参数传递给函数
- C++:访问作为函数参数传递的双指针数组所指向的变量的值
- 如何将 std::string 作为构造函数参数传递,并将其保存的 C 字符串存储在 void 指针中?
- 将派生类构造函数参数传递给受保护的成员
- 将指向数组的指针作为函数参数传递,这本身就是另一个函数的返回值?
- 如何将二维数组类型字符(字符串)作为函数参数传递?
- 有什么理由C++ 11+ std::mutex 应该声明为全局变量,而不是作为函数参数传递到 std::thread 中
- 如何将派生类作为函数参数传递:如果派生类成员不在父类中怎么办
- 如何将变量作为构造函数参数或函数参数传递
- 当数组对象以函数参数传递时,为什么复制构造函数会自称