はじめに
本記事は「pybind11でPython関数の引数にC++のインスタンスを渡す方法」の続きです。
環境構築や Makefile などは、上記記事をご覧ください。
こちらもCHECK
-
-
pybind11でPython関数の引数にC++のインスタンスを渡す方法
続きを見る
ここでは、Python 関数の戻り値をC++で実装したクラスとして返す方法を紹介します。
C++側のコード
C++ 側で Python 側から受け取るためのクラス AnalyzeData を定義します。
Python 側でも使えるように PyAnalyzeData というクラスを C++ 側から Python 側へ実装します。
ポイント
C++ 側で Python 側のクラスを実装する場合は、PYBIND11_EMBEDDED_MODULE を使います。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <algorithm> #include <iostream> #include <vector> #include <pybind11/pybind11.h> #include <pybind11/embed.h> #include <pybind11/stl.h> namespace py = pybind11; class AnalyzeData { public: int GetX() { return mX; } int GetY() { return mY; } void SetX(int x) { mX = x; } void SetY(int y) { mY = y; } private: int mX; int mY; }; PYBIND11_EMBEDDED_MODULE(PyAnalyzeData, m) { py::class_<AnalyzeData>(m, "PyAnalyzeData") .def(py::init<>()) .def_property("x", &AnalyzeData::GetX, &AnalyzeData::SetX) .def_property("y", &AnalyzeData::GetY, &AnalyzeData::SetY); } int main() { py::scoped_interpreter guard{}; py::object pydata = py::module_::import("PyAnalyzeData"); py::object pyfunc = py::module_::import("pymodule").attr("do_analyze"); auto result = pyfunc().cast<AnalyzeData>(); std::cout << "Python returned [" << result.GetX() << ", " << result.GetY() << "]" << std::endl; return 0; } |
前回と異なる点は、Python のクラスを実装する際の def __init__(self) 相当を実装していることです。
pybind11 で実装する .def(py::init<>()) が Python の def __init__(self) 相当になります。
また、Python からの戻り値はクラスインスタンスの実体になります。
クラスのポインターではないことに注意してキャスト・使用してください。
|
1 2 |
auto result = pyfunc().cast<AnalyzeData>(); |
Python 側のコード
Python 側では、C++ で実装した Python のモジュール、クラスを使用して戻り値を生成します。
|
1 2 3 4 5 6 7 8 9 10 |
import PyAnalyzeData as ad def do_analyze(): result = ad.PyAnalyzeData() result.x = 640 result.y = 480 return result |
PyAnalyzeData というモジュールとして C++ 側で実装しましたので、
先ずは import でモジュールを読込みます。
その後、そのモジュールの PyAnalyzeData クラスのインスタンスを生成し、
プロパティに値をセットして return します。
おわりに
いかがでしたでしょうか。
今回は、Python 側から クラスインスタンスを戻り値として返し、C++ 側で受け取る方法を紹介しました。
前回の内容と合わせると、双方向でクラスインスタンスをやり取りすることができるようになりますので、
pybind11 を使って Python と C++ を繋げて実現できる幅が広がったのではないでしょうか。