多线程boostpythonc++;PySide中的代码 我有C++代码,用PosithPython包装。这个想法是,我创建了一个共享对象,我的python GUI可以用来实例化包装C++函数的变量。 > C++代码做了一些提升操作,我希望能够使被包装的对象同时运行,这样GUI不会阻塞。< /P>

多线程boostpythonc++;PySide中的代码 我有C++代码,用PosithPython包装。这个想法是,我创建了一个共享对象,我的python GUI可以用来实例化包装C++函数的变量。 > C++代码做了一些提升操作,我希望能够使被包装的对象同时运行,这样GUI不会阻塞。< /P>,c++,python,multithreading,user-interface,boost-python,C++,Python,Multithreading,User Interface,Boost Python,我编译了一个用CMake包装的Boost Python共享对象,如下所示: find_package(Boost COMPONENTS system thread python REQUIRED) find_package(PythonLibs REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${PYTHON_INCLUDE_DIRS}) link_directories(${Boost_LIBRA

我编译了一个用CMake包装的Boost Python共享对象,如下所示:

find_package(Boost COMPONENTS system thread python REQUIRED)
find_package(PythonLibs REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${PYTHON_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
link_directories(${PYTHON_LIBRARIES})
set(Boost_USE_MULTITHREADED ON)
add_library(mynewlibinpython SHARED src/boost_python_wrapper_code.cpp)
target_link_libraries(mynewlibinpython ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} mylibincpp)
我可以用python很好地实例化该对象,但它会导致GUI阻塞。下面是我的python代码的一个通用片段:

from mynewlibinpython import *
class CppWrapper(QtCore.QObject):
    def __init__(self):
         super(CppWrapper,self).__init__()
         #some more initialization...

    @QtCore.Slot()
    def heavy_lifting_cpp_invocation():
         #constructor that takes a long time to complete
         self.cpp_object = CppObject()
在具有成员函数的对象中,当我按下GUI中的按钮时会触发该函数:

class GuiObjectWithUnimportantName:
     def __init__(self):
          #inititalization

          self.cpp_thread = QThread()
          self.cpp_wrapper = CppWrapper()

     def function_triggered_by_button_press(self):
          self.cpp_wrapper.moveToThread(self.cpp_thread)
          self.cpp_thread.started.connect(self.cpp_wrapper.heavy_lifting_cpp_invocation)
          print "starting thread"       
          self.cpp_thread.start()
          print "Thread started"      
所以cpp代码将开始执行它的任务,我也将从
print
语句(“开始线程”和“线程开始”)中立即获得输出


但是GUI被冻结了。这和python GIL有什么关系吗?我尝试将这些宏添加到
boost\u python\u wrapper\u code.cpp
并重新编译,但这会导致python GUI在启动时立即出现故障。

是的,我相信您的问题与GIL有关。下面是一个可能发生的简单示例:

from PyQt4 import QtCore, QtGui
import time

class Window(QtGui.QDialog):

    def __init__(self):
        super(Window, self).__init__()
        self.resize(200,100)

        layout = QtGui.QVBoxLayout(self)

        layout.addWidget(QtGui.QLineEdit())

        self.button1 = QtGui.QPushButton("Sleep")
        self.button1.clicked.connect(self.go_safe)
        layout.addWidget(self.button1)

        self.button2 = QtGui.QPushButton("Crunch")
        self.button2.clicked.connect(self.go_GIL_buster)
        layout.addWidget(self.button2)

    def go_safe(self):
        t = QtCore.QThread(self)
        heavy = Heavy()
        heavy.moveToThread(t)
        t.started.connect(heavy.safe)
        print "starting thread"
        t.start()
        print "thread started"
        self.t1 = t
        self.heavy1 = heavy

    def go_GIL_buster(self):
        t = QtCore.QThread(self)
        heavy = Heavy()
        heavy.moveToThread(t)
        t.started.connect(heavy.GIL_buster)
        print "starting thread"
        t.start()
        print "thread started"
        self.t2 = t
        self.heavy2 = heavy

class Heavy(QtCore.QObject):

    def safe(self):
        print "Sleeping"
        time.sleep(10)
        print "Done"

    def GIL_buster(self):
        print "Crunching numbers"
        x = 2
        y = 500000000
        foo = x**y
        print "Done"


if __name__ == "__main__":
    app = QtGui.QApplication([])
    win = Window()
    win.show()
    win.raise_()
    app.exec_()
当您单击第一个按钮时,线程将睡眠10秒,您将注意到您仍然可以在文本字段中键入内容。睡眠释放GIL,以便主线程可以继续工作

当您单击第二个按钮时,线程将执行一个大数操作。这将始终获取GIL,GUI将锁定直到完成

如果您的boost扩展没有以任何方式处理python对象,我认为您可以为其操作释放GIL。这样就不会阻塞GUI。如果您在python对象上执行繁重的操作,那么这里可能会有问题

在任何函数中都可以使用一个函数来在该函数期间释放GIL(当helper实例被销毁时)

使用它

int foo_wrapper(int x)
{
    ScopedGILRelease scoped;
    return foo(x);
}

其他人在这个repo中还有一些使用这个技巧的例子:

好吧,如果我理解正确的话,你的解决方案包括在.cpp包装器源代码或.cpp原始源代码周围使用
Py\u BEGIN\u ALLOW\u THREADS
Py\u END\u ALLOW\u THREADS
?是的,无论公约如何促进获得和发放gil。只要代码没有修改python对象,您就可以围绕该函数发布gil。感谢链接到gil发布类。工作完美。
int foo_wrapper(int x)
{
    ScopedGILRelease scoped;
    return foo(x);
}