你不能轻易做到:C++ 函数指针仅存储内存中该函数代码开始的位置(或类似的、特定于实现的内容),而 Python 函数是一个完整的 Python 对象,带有存储字节码的字典(可能是未编译的 Python 代码)、文档字符串和其他一些位。它也不是机器可以独立运行的形式——它需要 Python 解释器来处理字节码。实际上没有办法将所有内容存储在 C++ 函数指针中。
你可以做的是使用 C++11std::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
class (http://www.boost.org/doc/libs/1_58_0/libs/python/doc/v2/object.html#object_operators-spec http://www.boost.org/doc/libs/1_58_0/libs/python/doc/v2/object.html#object_operators-spec)具有您需要的功能。您可以轻松地从 Cython 获取 PyObject*
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 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)));
Since o
是可调用的,你应该可以直接在std::function
Foo foo; // a foo object
foo.setFooFunction(o); // pass it the boost::python::object
(显然这里缺少很多细节,但希望广泛的方法会有用!)