2016-08-29 12 views
0

私は複数のスレッドで動作するC++のdllを持っています。 私はこのライブラリをCythonでラップし、特殊な受信側のコールバック関数を作成しました。これはasyncio.Queueにいくつかの結果を追加する必要があります。将来の addの結果をCythonの別のスレッドからキューに入れる方法は?

私はこれを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

+0

受信者を呼び出すメインコードをどのように開始しますか? – michitux

+0

@michituxソースリンクを追加しました。 '.py'ではcythonクラスを' .pyx'から初期化し、cythonクラスは '.h'と' .cpp'からcppクラスを初期化し、cppクラスはコールバックを渡してTeamSpeak3 APIを呼び出します。 生のシンプルコード。 – Broly

答えて

1

これは推測のビットですが、あなたはおそらく、それはGILを保持し、それを解放することはありませんです実行しているCython/C/C++ループを持っています。コールバックはそれから永遠に待たされます。

普通のPythonコードでは、別のスレッドがそれを待っている場合、いくつかの命令ごとにGILが解放されます。 Cythonでは自動的には発生しません。それはそう頻繁に、すべてが起こるのないことを保証する一つの方法は、あなたのループにすることです。

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

これはGILは一度ループごとにリリースされることを確実にします。

残念ながら、メインループがある場所はわかりません。

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

助けるかもしれない:それはあなたのPyTeamSpeak3クラスでconnect内だし、多分に接続の定義を変更する場合、私は疑問に思いますか?

+0

NewMessageで "nogil"と共に使用するとうまくいきません。しかし、私は何もPythonの操作を行うことはできません... 多分私はmutexとC + +のキューに値を格納することができますメインのpythonスレッドのすべての値をポップ? しかし、それは松葉杖と臭いのように見える... :( – Broly

+0

おそらく答えはhttp://stackoverflow.com/questions/11687960/how-to-call-a-multi-threaded-c-function-in-cythonもしコールバックが別のスレッドから呼び出されていれば、スレッドを登録するこれらの追加ステップが必要だと思います。私はこの回答に同意できますが、私は同様のコードを持っています。 – michitux

+0

@michitux Cythonは 'with the gil:'と書いたとき、実際には[the link](https://docs.python.org/3/c-api/init.html#non-python-created-threads) 'それはOK(私は同様の考えを持っていた)でなければなりません。私はまだこの答えが問題だと思っていますが、ループがどこにあるのか分かりません。 – DavidW

関連する問題