在单独的线程中将boost :: python :: object作为函数调用

时间:2013-11-21 09:13:40

标签: c++ python multithreading boost

我试图在boost :: python的帮助下将一些c ++功能包装到python中。我在使特定的回调机制工作时遇到了一些麻烦。以下代码段解释了我要做的事情:

//c++ side
class LoopClass {

    public: 
    //some class attributes

    void call_once(std::function const& fun) const;
};

void callOnce(LoopClass& loop, boost::python::object const& function) {

    auto fun = [&]() {
        function();
    };

    loop->call_once(fun);
}

boost::python::class_<LoopClass>("LoopClass")
     .def("call_once", &callOnce);


//python side
def foo():
    print "foo"    

loop = LoopClass()
loop.call_once(foo)

以下是交易:函数call_once()占用std::function并将其放入队列中。 LoopClass维护一个永久循环,它在一个单独的线程中运行,并在某一点处理存储的回调函数的队列。要使boost::python::object作为函数,必须显式调用强制转换运算符。这就是为什么我没有直接包装call_once(),而是写了一个小转换函数callOnce(),它通过lambda转发转换操作符调用。

无论如何,当我尝试运行此代码时,访问boost::python::object失败并出现分段错误。我想在线程之间共享python对象并不容易。但是怎么做呢?

提前感谢您的帮助!

更新

我试图遵循@JanneKarila的建议

  

Non-Python created threads。 - Janne Karila

我想这是找到解决方案的正确点,但不幸的是我无法弄清楚如何应用它。

我试过

void callOnce(LoopClass& loop, boost::python::object const& function) {

    auto fun = [&]() {
        PyGILState_STATE gstate;
        gstate = PyGILState_Ensure();

        function();

        PyGILState_Release(gstate);
    };

    loop->call_once(fun);
}

哪个不起作用。我错过了什么或者太愚蠢了吗?

1 个答案:

答案 0 :(得分:0)

你有没有打过PyEval_InitThreads(); ?

如果是这样的话,这个http://www.codevate.com/blog/7-concurrency-with-embedded-python-in-a-multi-threaded-c-application片段可以提供帮助吗?