C++通过Swig跨线程回调Python代码

C++ 定义 Callback 类. PyThreadStateLock 保证垮线程调用成功:

 

 

#include <Python/Python.h>
class Callback
{
public:
    Callback(){}
    
    virtual ~Callback(){}
    virtual void call(ObjWithPyCallback& object){}
};

class ObjWithPyCallback
{
public:
    
    ObjWithPyCallback();
    ~ObjWithPyCallback();
    void setCallback(Callback &callback);
    void call(); 
    
private:
    void NotifyThread();
    Callback* callback_;
};
class PyThreadStateLock { public: PyThreadStateLock(void) { state = PyGILState_Ensure( ); } ~PyThreadStateLock(void) { PyGILState_Release( state ); } private: PyGILState_STATE state; };

 

Callback.cpp

 

ObjWithPyCallback::ObjWithPyCallback() : callback_(NULL)
{
    Py_Initialize();
    PyEval_InitThreads();
    PyEval_ReleaseLock();
}

ObjWithPyCallback::~ObjWithPyCallback()
{    
}

void ObjWithPyCallback::setCallback(Callback &callback)
{
    callback_ = &callback;
}

void ObjWithPyCallback::call()
{
    if ( ! callback_ )
    {
        std::cerr << "No callback is set.\n";
    }
    else
    {
        thread(&ObjWithPyCallback::NotifyThread, this).detach();//call in another thread
        //callback_->call(*this);//call directly
        
    }
}

void ObjWithPyCallback::NotifyThread()
{
    class PyThreadStateLock PyThreadLock;//fix segmentation fault 
    callback_->call(*this);
}

 

.i 文件中

%module(directors="1") cb
%{
   #include "Callback.h"
%}
%feature("director") Callback;

%include "Callback.h"

 

在 python 中调用:

 

import cb

class CB(cb.Callback):
    def __init__(self):
        super(CB, self).__init__()
    def call(self, x):
        print("Hello from CB!")
        print(x)

o = cb.ObjWithPyCallback()
mycb=CB()
o.setCallback(mycb)
o.call()

 

posted @ 2019-10-14 15:04  西北望射天狼  阅读(648)  评论(0编辑  收藏  举报