使用boost :: python公开具有std :: function作为参数的C ++成员函数 [英] Expose C++ member function that has std::function as argument with boost::python
问题描述
我有一个包含一个属性的类,该属性是std :: function.我使用成员函数设置了此属性的值,因此该类如下所示:
I have a class that contains an attribute which is a std::function. I set the value of this attribute using a member function, so the class looks like this:
class ClassName
{
public:
void SetCallbackFunction(std::function<void (int i)> callbackFun) {
m_callbackFunction = callbackFun;
}
protected:
std::function<void (int i)> m_callbackFunction;
};
我需要将该类公开给Python,当然,我需要公开SetCallbackFunction
函数.
如何使用boost :: python做到这一点?
I need to expose this class to Python and, of course, I need to expose the SetCallbackFunction
function.
How can I do this with boost::python?
推荐答案
由于Python对象既是Callable对象又是CopyConstructible对象,所以最简单的方法是将辅助函数公开为SetCallbackFunction
并接受boost::python::object
,然后将其委托给实际的SetCallbackFunction
函数:
As Python objects are both Callable and CopyConstructible, the simplest approach is to expose an auxiliary function as SetCallbackFunction
that accepts a boost::python::object
, then delegates to the actual SetCallbackFunction
function:
void ClassName_SetCallbackFunction_aux(ClassName& self, boost::python::object object)
{
self.SetCallbackFunction(object);
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<ClassName>("ClassName", python::init<>())
.def("set_callback", &ClassName_SetCallbackFunction_aux)
// ...
;
}
当ClassName::SetCallbackFunction
直接暴露给Python并被调用时,Boost.Python将在运行时搜索其注册表以找到std::function<void (int)>
的from-Python转换器.由于尚未明确注册此转换,因此Boost.Python将无法分派函数调用.辅助功能避免了此运行时转换检查,并从boost::python::object
构造了std::function<void (int)>
对象,因为boost::python::object
既是Callable的又是CopyConstructible的.
When ClassName::SetCallbackFunction
is directly exposed to Python and invoked, Boost.Python will search its registry at runtime to locate a from-Python converter for std::function<void (int)>
. As this conversion has not been explicitly registered, Boost.Python will fail to dispatch the function call. The auxiliary function avoids this runtime conversion check and constructs a std::function<void (int)>
object from a boost::python::object
, as the boost::python::object
is both Callable and CopyConstructible.
下面是一个示例演示,该示例使用辅助函数将Python对象分配为回调:
Here is an example demonstrating using an auxiliary function to assign Python objects as callbacks:
#include <functional> // std::function
#include <boost/python.hpp>
// Legacy API.
class spam
{
public:
void SetCallbackFunction(std::function<void (int)> callback)
{
callback_ = callback;
}
void perform(int x)
{
callback_(x);
}
private:
std::function<void (int)> callback_;
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose spam.
python::class_<spam>("Spam", python::init<>())
// Use an auxiliary function to set Python callbacks.
.def("set_callback", +[](spam& self, boost::python::object object) {
self.SetCallbackFunction(object);
})
.def("perform", &spam::perform)
;
}
互动用法:
>>> import example
>>> called = False
>>> def perform_x(x):
... assert(42 == x)
... global called
... called = True
...
>>> spam = example.Spam()
>>> spam.set_callback(perform_x)
>>> assert(not called)
>>> spam.perform(42)
>>> assert(called) # Verify callback was invoked
>>> spam.set_callback(lambda: None)
>>> try:
... spam.perform(42)
... assert(False) # Verify callback fails (the lambda accepts no args)
... except TypeError:
... pass
...
这篇关于使用boost :: python公开具有std :: function作为参数的C ++成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!