I want to use this python module: https://python-omxplayer-wrapper.readthedocs.io/en/latest/ on my c++ app.
It is a omxplayer python wrapper and has some callback events that I want to link to my c++ class function member.
I did it with success using a static function like this:
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 );
Where OMXPlayer
is my c++ class.
I tried to use boost::bind and boost::function without success.
How can use OMXPlayer::onPause()
function instead of static foo
function?
Edit with example:
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 function:
#include "OMXPlayer.h"
int main(){
OMXPlayer player1("/root/Setteventi.mp4", std::vector<std::string> {"--loop"}, false, "org.mpris.MediaPlayer2.omxplayer1");
player1.pause();
}
You can see the python Class from here: https://python-omxplayer-wrapper.readthedocs.io/en/latest/_modules/omxplayer/player/
When eventPause on python side is called it throw this:
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})
Ok, with @pptaszni help I found how to do it.
The problem was that boost could not detarmine the function signature because boost::bind
return a function object.
To avoid this problem, I have to specify the signature when call make_function
.
Example:
pyOMXPlayer.attr("pauseEvent") = py::make_function( boost::bind(&OMXPlayer::onPause, this, _1), py::default_call_policies(), boost::mpl::vector<void, py::object>() );
The tricky part is the last argument of py::make_function
Thanks @pptaszni