C++アプリケーションにおけるPybind11を用いたPythonスクリプト実行とメモリデータ操作

Pybind11概要

Pybind11はC++とPython間のシームレスな連携を実現する軽量ライブラリです。公式リポジトリおよびドキュメントは以下の通りです:

重要な注意点として、Pythonインタプリタはグローバルに単一インスタンスのみ許可され、ポインタや参照の取り扱いには特別な配慮が必要です。

Python環境のセットアップ

Python 3.6以上が動作する環境が必要です。開発環境では移植性を考慮し、環境構築後は他のマシンへのコピーが可能な状態にすることが推奨されます。

基本的な使用例

C++関数をPythonから呼び出す最小限の実装例:

#include <pybind11/pybind11.h>

namespace py = pybind11;

int compute_sum(int a, int b) {
    return a + b;
}

PYBIND11_MODULE(sample_module, m) {
    m.doc() = "サンプルモジュール";
    m.def("compute_sum", &compute_sum, "二つの整数の和を計算", 
          py::arg("x") = 5, py::arg("y") = 3);
}

CMakeを使用する場合、生成するライブラリの拡張子を.pydに変更:

set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".pyd")

Python側での使用方法:

from sample_module import compute_sum
output = compute_sum(8, 4)

C++アプリケーション内でのPythonインタプリタ埋め込み

外部Pythonスクリプトを実行するための手順:

  1. 必要な構造体や変数をエクスポートする.pydファイルを準備
  2. アプリケーション内でPythonインタプリタを初期化
  3. インターフェースを提供し、スクリプト実行機能を実装

基本的なインタプリタの埋め込み例:

#include <pybind11/embed.h>
#include <iostream>

namespace py = pybind11;

int main() {
    py::scoped_interpreter interpreter{};
    py::module custom_script = py::module::import("custom_script");
    int value = custom_script.attr("compute_sum")(3, 7).cast<int>();
    std::cout << "計算結果: " << value << std::endl;
    return 0;
}

Pythonファイルを直接実行する例:

py::object sys = py::module::import("sys");
py::list path_list = sys.attr("path");
path_list.attr("append")(script_directory);

py::list clear_args;
sys.attr("argv") = clear_args;
py::list arguments = sys.attr("argv");

for (const auto& arg : argument_list) {
    arguments.append(arg);
}

py::eval_file(script_file_path.c_str());

sys.attr("argv") = clear_args;
path_list.attr("remove")(script_directory);

実装上の注意点と問題対策

  • 公式ドキュメントを詳細に確認することが重要
  • 特定のモジュール(例: OpenCV)はアンロード後に再読み込みするとクラッシュする可能性あり
  • マルチスレッド環境ではGIL(Global Interpreter Lock)の取り扱いに注意
  • エラーハンドリング時のデッドロックを避けるため、適切なロック管理を実装

タグ: pybind11 C++ Python embedded-scripting Memory-Management

6月17日 18:45 投稿