在Python上运行独立的线程上输出的C++函数的问题

2024-04-24 07:54:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个小模块,它使用RtMidi库从MIDI设备接收MIDI输入: http://www.music.mcgill.ca/~gary/rtmidi/

我没有问题使用图书馆,它工作得很好。我已经使用Cython导出了模块以与Python一起使用。该模块可以很好地导入Python,并且可以正确地使用Python。问题是,由于它无限期地等待用户MIDI输入,所以有必要在自己的线程中生成它。在

我已经在C++中使用STD::Trand测试了它自己的线程,它工作得很好。问题是在使用导出的库时,特别是试图在Python内部的自己的线程上生成它。在

代码如下:

    import midi   #my exported C++ module
    import threading
    import time

    def test():
      for i in range(0, 10):
        print(i)
        time.sleep(.25)

    my_thread = threading.Thread(target=test)
    my_thread.daemon = False
    my_thread.start()

    midi_input = midi.MidiListen()
    midi_input.start()   #listen for MIDI input indefinitely

最后,我生成的线程将打印“0”,然后MIDI输入读取器将启动,并且第一个线程在MIDI之前不会继续打印_输入.启动()函数返回,而不是两个函数同时运行。在

另外,我试着用另一种方式运行这个代码_输入.启动()在单独的线程上执行,而不是test()函数。在

我做错什么了?在

编辑: 多亏了杰夫的回答,我才得以解决问题。在

注意函数声明末尾的“nogil”和“with gil”。在

这是我的.pyx文件:

^{pr2}$

下面是最后一个Python脚本:

import midi
import threading
import time


def test():
    for i in range(0, 10):
        print(i)
        time.sleep(.25)

def start():
    x = midi.MidiListen()
    x.start_midi()

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

test()

Tags: 模块函数testimportforinputtimemy
1条回答
网友
1楼 · 发布于 2024-04-24 07:54:33

这是因为Python的全局解释器锁(GIL)。一次只允许一个线程在Python解释器中运行。为了解决您的问题,您应该在调用RtMidi之前释放GIL。Cython手册在Acquiring and Releasing the GIL一节中对此进行了讨论。在

你的新代码看起来像

def start(self):
    with nogil:
        # Call rtmidi functions

但是,如果要操作任何Python对象,例如在回调中,则必须获取GIL。看起来RtMidi是面向回调的,所以如果您当前有

^{pr2}$

你应该把它改成

cdef void callback(...) with gil:
    # The same code as before

这导致Cython发出代码,在运行函数体之前获得GIL锁。在

相关问题 更多 >