boost::python 如何使用函数成员作为 python 回调
boost::python how to use function member as python callback
我想在我的 C++ 应用程序上使用这个 python 模块:https://python-omxplayer-wrapper.readthedocs.io/en/latest/。
它是一个 omxplayer python 包装器并且有一些我想 link 到我的 c++ class 函数成员的回调事件。
我使用这样的静态函数成功地做到了:
void foo(py::object player) {
std::cout << "pause event callback" << std::endl;
}
py::object mod = py::import("omxplayer.player");
OMXPlayer::pyOMXPlayer = mod.attr("OMXPlayer")(_file, args, NULL, NULL, _dbus_name, _pause);
OMXPlayer::pyOMXPlayer.attr("pauseEvent") = py::make_function( &foo );
其中 OMXPlayer
是我的 c++ class.
我尝试使用 boost::bind 和 boost::function 但没有成功。
如何使用 OMXPlayer::onPause()
函数代替 static foo
函数?
用例子编辑:
OMXPlayer.cpp
#include "OMXPlayer.h"
OMXPlayer::OMXPlayer(std::string _file,
std::vector<std::string> _args,
bool _pause,
std::string _dbus_name){
try{
Py_Initialize();
py::object mod = py::import("omxplayer.player");
py::list args;
for(auto const& value: _args) {
args.append(value);
}
OMXPlayer::pyOMXPlayer = mod.attr("OMXPlayer")(_file, args, NULL, NULL, _dbus_name, _pause);
pyOMXPlayer.attr("pauseEvent" ) = py::make_function(&OMXPlayer::onPause);
OMXPlayer::active = false;
}
catch(py::error_already_set){
PyErr_Print();
}
}
void OMXPlayer::onPause(){
std::cout << "onPause" << std::endl;
}
void OMXPlayer::pause(){
try{
OMXPlayer::pyOMXPlayer.attr("pause")();
}
catch(py::error_already_set){
PyErr_Print();
}
}
OMXPlayer.h
#include <boost/python.hpp>
#include <boost/function.hpp>
#include <vector>
#include <iostream>
#include <atomic>
namespace py = boost::python;
class OMXPlayer{
public:
OMXPlayer(std::string _file,
std::vector<std::string> _args,
bool _pause = false,
std::string _dbus_name = "");
void pause();
void onPause();
};
main.cpp函数:
#include "OMXPlayer.h"
int main(){
OMXPlayer player1("/root/Setteventi.mp4", std::vector<std::string> {"--loop"}, false, "org.mpris.MediaPlayer2.omxplayer1");
player1.pause();
}
您可以从这里看到 python Class:https://python-omxplayer-wrapper.readthedocs.io/en/latest/_modules/omxplayer/player/
当调用 python 端的 eventPause 时抛出:
Traceback (most recent call last):
File "<decorator-gen-56>", line 2, in pause
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 48, in wrapped
return fn(self, *args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 550, in pause
self.pauseEvent(self)
Boost.Python.ArgumentError: Python argument types in
None.None(OMXPlayer)
did not match C++ signature:
None(OMXPlayer {lvalue})
Traceback (most recent call last):
File "<decorator-gen-56>", line 2, in pause
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 48, in wrapped
return fn(self, *args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 550, in pause
self.pauseEvent(self)
Boost.Python.ArgumentError: Python argument types in
None.None(OMXPlayer)
did not match C++ signature:
None(OMXPlayer {lvalue})
好的,在@pptaszni 的帮助下,我找到了方法。
问题是 boost 无法确定函数签名,因为 boost::bind
return 一个函数对象。
为避免此问题,我必须在调用时指定签名 make_function
。
示例:
pyOMXPlayer.attr("pauseEvent") = py::make_function( boost::bind(&OMXPlayer::onPause, this, _1), py::default_call_policies(), boost::mpl::vector<void, py::object>() );
棘手的部分是 py::make_function
的最后一个参数
谢谢@pptaszni
我想在我的 C++ 应用程序上使用这个 python 模块:https://python-omxplayer-wrapper.readthedocs.io/en/latest/。
它是一个 omxplayer python 包装器并且有一些我想 link 到我的 c++ class 函数成员的回调事件。
我使用这样的静态函数成功地做到了:
void foo(py::object player) {
std::cout << "pause event callback" << std::endl;
}
py::object mod = py::import("omxplayer.player");
OMXPlayer::pyOMXPlayer = mod.attr("OMXPlayer")(_file, args, NULL, NULL, _dbus_name, _pause);
OMXPlayer::pyOMXPlayer.attr("pauseEvent") = py::make_function( &foo );
其中 OMXPlayer
是我的 c++ class.
我尝试使用 boost::bind 和 boost::function 但没有成功。
如何使用 OMXPlayer::onPause()
函数代替 static foo
函数?
用例子编辑:
OMXPlayer.cpp
#include "OMXPlayer.h"
OMXPlayer::OMXPlayer(std::string _file,
std::vector<std::string> _args,
bool _pause,
std::string _dbus_name){
try{
Py_Initialize();
py::object mod = py::import("omxplayer.player");
py::list args;
for(auto const& value: _args) {
args.append(value);
}
OMXPlayer::pyOMXPlayer = mod.attr("OMXPlayer")(_file, args, NULL, NULL, _dbus_name, _pause);
pyOMXPlayer.attr("pauseEvent" ) = py::make_function(&OMXPlayer::onPause);
OMXPlayer::active = false;
}
catch(py::error_already_set){
PyErr_Print();
}
}
void OMXPlayer::onPause(){
std::cout << "onPause" << std::endl;
}
void OMXPlayer::pause(){
try{
OMXPlayer::pyOMXPlayer.attr("pause")();
}
catch(py::error_already_set){
PyErr_Print();
}
}
OMXPlayer.h
#include <boost/python.hpp>
#include <boost/function.hpp>
#include <vector>
#include <iostream>
#include <atomic>
namespace py = boost::python;
class OMXPlayer{
public:
OMXPlayer(std::string _file,
std::vector<std::string> _args,
bool _pause = false,
std::string _dbus_name = "");
void pause();
void onPause();
};
main.cpp函数:
#include "OMXPlayer.h"
int main(){
OMXPlayer player1("/root/Setteventi.mp4", std::vector<std::string> {"--loop"}, false, "org.mpris.MediaPlayer2.omxplayer1");
player1.pause();
}
您可以从这里看到 python Class:https://python-omxplayer-wrapper.readthedocs.io/en/latest/_modules/omxplayer/player/
当调用 python 端的 eventPause 时抛出:
Traceback (most recent call last):
File "<decorator-gen-56>", line 2, in pause
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 48, in wrapped
return fn(self, *args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 550, in pause
self.pauseEvent(self)
Boost.Python.ArgumentError: Python argument types in
None.None(OMXPlayer)
did not match C++ signature:
None(OMXPlayer {lvalue})
Traceback (most recent call last):
File "<decorator-gen-56>", line 2, in pause
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 48, in wrapped
return fn(self, *args, **kwargs)
File "/usr/local/lib/python3.7/dist-packages/omxplayer/player.py", line 550, in pause
self.pauseEvent(self)
Boost.Python.ArgumentError: Python argument types in
None.None(OMXPlayer)
did not match C++ signature:
None(OMXPlayer {lvalue})
好的,在@pptaszni 的帮助下,我找到了方法。
问题是 boost 无法确定函数签名,因为 boost::bind
return 一个函数对象。
为避免此问题,我必须在调用时指定签名 make_function
。
示例:
pyOMXPlayer.attr("pauseEvent") = py::make_function( boost::bind(&OMXPlayer::onPause, this, _1), py::default_call_policies(), boost::mpl::vector<void, py::object>() );
棘手的部分是 py::make_function
谢谢@pptaszni