Boost :: Python:安全地存储Python可调用的及其参数以便稍后调用它

时间:2016-07-26 15:34:32

标签: python c++ boost-python

我想为C ++组件 invoker 创建一个Python绑定 函数对象,稍后从另一个线程调用 。 C ++中的用法如下所示:

invoker my_invoker(thread_holding_context);

// this will queue ome_class::some_method() to be executed later in another
// thread and it returns immediately
my_invoker.invoke(std::bind(&some_class::some_method, this));

当然,您可以使用纯Python代码而不是包装C ++ 组件,但此invoker是更大的框架的一部分 上下文,我 使用它。

在Boost :: Python中,包装器可能如下所示:

struct invoker_wrap 
    : public invoker, public wrapper<invoker> {
    explicit invoker_wrap(thread_holding_context) {...}

    void wrap_invoke(boost::python::object callable) {
        // queue the callable - don't execute it yet
        invoker::invoke(std::bind(&invoker_wrap::call, this, callable));
    }

    void call(boost::python::object callable) {
        std::cout << "call: " << callable.ptr() << std::endl;
        PyGILState_STATE gstate = PyGILState_Ensure();  // seems to be not needed
        callable();
        PyGILState_Release(gstate);                     // seems to be not needed
    }
};

class_<invoker_wrap, boost::noncopyable>("invoker", init<thread_holding_context &>())
    .def("invoke", &invoker_wrap::wrap_invoke);

Python代码与此类似:

_invoker = invoker(thread_holding_context)

def my_func():
    print("%.1f %s: my_func()" % (time.time(), threading.currentThread().getName()))

def thread_func():
    while True:
        _invoker.invoke(my_func)
        time.sleep(1)

threading.Thread(target=thread_func).start()

这段代码在某种程度上有效 - 但它表现得很奇怪。 invoker::call正在发生 调用正确但但是执行了callable本身的输出 很久以后(准确地说最多57秒)。

我现在有两个问题:

  • 因为invoker不立即运行可调用对象但存储它 一个队列,invoke()在调用之前返回,Python应该清理 呼叫所需的所有数据。不是吗? 我应该复制保护 callable和所有参数吗? 怎么办呢?

  • 为什么Python代码的输出会在以后的C ++中打印出来 输出不是?由于C ++代码和Python代码运行相同 他们共享的流程stdout。我可以通过电话解决这个问题 回调中sys.stdout.flush(),但我不明白为什么。

0 个答案:

没有答案