如何设置未来的结果\从Cython中的另一个线程添加到队列?

时间:2016-08-29 09:32:47

标签: python c++ multithreading cython gil

我有C ++ dll,可以使用多个线程。 所以我用Cython包装了这个库并创建了特殊的接收器回调函数,它必须在asyncio.Queue中添加一些结果。

cdef void __cdecl NewMessage(char* message) nogil:

我把它标记为nogil,这个回调来自另一个线程。 在这个回调中我只使用:

with gil:
   print("hello")  # instead adding to Queue. print("hello") is more simple operation to demostrate problem

这里遇到了僵局。 如何解决?

C ++回调声明(标题):

typedef void (*receiver_t)(char*);
void SetReceiver(receiver_t new_rec);

CPP:

static receiver_t receiver = nullptr;

void SetReceiver(receiver_t new_rec)
{
    printf("setted%i\n", (int)new_rec);
    a = 123;
    if (new_rec != nullptr)
        receiver = new_rec;
}

Cython代码:

cdef extern from "TeamSpeak3.h":
    ctypedef void (*receiver_t) (char*) nogil
    cdef void __cdecl SetReceiver(receiver_t new_rec) nogil

cdef void __cdecl NewMessage(char* message) nogil:
    with gil:
        print("hello")

SetReceiver(NewMessage)

完整代码: .h http://pastebin.com/ZTCjc6NA

.cpp http://pastebin.com/MeygA8im

.pyx http://pastebin.com/k4X9c54P

.py http://pastebin.com/1YV7tMiF

1 个答案:

答案 0 :(得分:1)

这是一个猜测,但你可能有一个Cython / C / C ++循环运行,持有GIL并且从不释放它。然后强制回调等待它。

在普通的Python代码中,如果另一个线程正在等待它,则每隔几条指令释放一次GIL。在Cython中不会自动发生。确保它经常发生的一种方法是循环:

while True:
   # ... do stuff
   with nogil:
      pass

这确保了每个循环释放一次GIL。

不幸的是,对于我有主循环的地方来说,这并不明显。我想知道它是否在connect类中的PyTeamSpeak3内,并且可能将连接的定义更改为:

def connect(self):
    with nogil:
       self.thisptr.Connect()

可能会有帮助吗?