【发布时间】:2020-11-14 02:51:35
【问题描述】:
我想在我的 c++ 应用程序上使用这个 python 模块:https://python-omxplayer-wrapper.readthedocs.io/en/latest/。
它是一个 omxplayer python 包装器,并且有一些我想链接到我的 c++ 类函数成员的回调事件。
我使用这样的静态函数成功地做到了:
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++ 类。
我尝试使用 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类: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})
【问题讨论】:
-
来自boost docs: "如果 F 是一个指向成员函数的指针类型,函数调用的目标对象 (*this) 将从第一个 Python 参数中获取,随后Python 参数将用作 f 的参数。”那么,您是否尝试简单地传递
&OMXPLayer::onPause?结果是什么?显示完整的示例。 -
是的,我已经尝试过你说的方法,但是它不起作用,因为函数签名不同,从我编辑的示例中可以看出。
-
嗯,是的,因为 python 用
self调用它,这是一个不同的OMXPlayer类。如果你boost::bind或std::bindthis指针,错误是什么? -
我不能或者我不知道怎么做。如果我只是尝试:
pyOMXPlayer.attr("pauseEvent" ) = py::make_function( boost::bind(&OMXPlayer::onPause, this) );它不会编译错误:/usr/include/boost/python/make_function.hpp:104:57: error: no matching function for call to ‘get_signature(boost::_bi::bind_t<void, boost::_mfi::mf0<void, OMXPlayer>, boost::_bi::list1<boost::_bi::value<OMXPlayer*> > >&)’ f,default_call_policies(), detail::get_signature(f));make_function 需要一个函数并且 boost:bind 返回一个对象。 -
应该或多或少:
py::make_function(boost::bind(&OMXPlayer::onPause, this));或者更确切地说是py::make_function(boost::bind(&OMXPlayer::onPause, this, _1));和签名:void onPause(py::object player),因为 python 用一个参数调用它。或者使用标准库:py::make_function(std::bind(&OMXPlayer::onPause, this, std::placeholders::_1));抱歉没有更准确,今天我没有任何好的环境来尝试你的代码。
标签: python c++ boost-python