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