我编写了一个小模块,它使用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()
这是因为Python的全局解释器锁(GIL)。一次只允许一个线程在Python解释器中运行。为了解决您的问题,您应该在调用RtMidi之前释放GIL。Cython手册在Acquiring and Releasing the GIL一节中对此进行了讨论。在
你的新代码看起来像
但是,如果要操作任何Python对象,例如在回调中,则必须获取GIL。看起来RtMidi是面向回调的,所以如果您当前有
^{pr2}$你应该把它改成
这导致Cython发出代码,在运行函数体之前获得GIL锁。在
相关问题 更多 >
编程相关推荐