2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++11 thread を使うコードを pybind11 で wrap するメモ

Posted at

背景

  • C++ 側で thread 使うコード(e.g. OpenGL window を表示する)を書いていて, それを pybind11 で wrap したい.

普通にやるとクラッシュして何が原因なの? と半営業日くらい原因不明で悩んでしまいます :cry:
GIL の管理が必要です.

構成

以下のように, loop のある関数を C++11 thread で書いているとします
(実際は thread 化してなくても同様と思われる. また pthread など他のスレッド関数使っても同様)

void renderThread(std::atomic<bool> *quit) {

  while (...) {
    if (quit && ((*quit) == true)) {
      break;
    }

    draw();
  }
}

...

void start_opengl() {
  _quit = false;
  _th = std::thread(renderThread, &quit);
}

void end_opengl() {
  _quit = false;
  _th.join();
}

ここで start_opengl()end_opengl() をそのまま pybind11 で wrap して呼び出すとクラッシュします.

GIL が原因でした.

にあるように, 実行が長くなるコード(or thread を起動するコード)には GIL release

py::gil_scoped_release guard;

を, thread が終了する(join() を呼ぶところ)には GIL acquire

py::gil_scoped_acquire guard;

をはさみます. C++ コードに記入だと pybind11 ヘッダのインクルードが発生して面倒なので, pybind11 binding のところで定義するのがよいでしょう.

m.def("start_opengl", []() {
  py::gil_scoped_release guard;
  start_opengl();
});

m.def("end_opengl", []() {
  py::gil_scoped_aquire guard;
  end_opengl();
});

のように.

ただ, C++ からさらに python を呼んだりと複雑な場合はこれではうまくいかなそうです!

上記 github issue にあるように, pybind11 GIL aquire/release は諦め, python multiprocessing で python 世界でスレッド管理するようにするのがよさそうです.

TODO

  • Python -> C++ thread へ中断やデータを渡すうまい方法を考える
    • とりあえず中断とかは std::atomic<bool> でフラグでいけるが... JSON-RPC あたりで http メッセージ通信とかにしたほうがいいかも(C++ 側で JSON パースが面倒であるのと, そこまでやるなら C++ と python でプロセス切り分けたほうが良さそうであるが...)
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?