はじめに
PythonとC++を連携させることができるpybind11
では、
STLコンテナを介することでPythonからC++の関数にリストを渡すことができます。
外部リンク:pybind11を使ってPythonからC++コードを実行する方法
しかしこれは値渡しになるため、更新したリストをPythonで使うにはC++側で返り値にする必要があります。
一方、既存のC++資産を使う場合にはできるだけC++のソースコードに手を加えたくないので、
新たに返り値を設定したり更新のところを書き換えたりしたくないことがあります。
そこで、リストではなくNumpyを介することで、
用途は限定的ではありますが参照渡しができるので共有します。
基本的には以下のリンクで解説されているmutable_data
やEigen
を使うのがいいと思うのですが、
それ以外にもこんなやり方があるというくらいの内容です。
外部リンクpybind11入門(3) NumPy連携その1
外部リンクpybind11入門(3) NumPy連携その2
注意点
- pybindのインストール方法、基本的な利用方法は説明しません
- pybindおよびC++は浅い知識しかないので誤りがありましたらコメントください
C++コード
STLコンテナを介してリストを渡す関数update1()
と、Numpyで渡す関数update2()
を定義します。
どちらも受け取った配列の値を1.0に更新しようとするものです。
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <vector>
namespace py = pybind11;
void update1(std::vector<double> &x)
{
int i;
for(i = 0; i < 3; i ++)
{
x[i] = 1.0;
}
}
void update2(py::array_t<double> x)
{
auto x_buf = x.request();
double *x_ptr = (double *)x_buf.ptr;
int i;
for(i = 0; i < 3; i ++)
{
x_ptr[i] = 1.0;
}
}
PYBIND11_MODULE(hoge, m)
{
m.doc() = "hoge module";
m.def("update1", &update1, "update1 function");
m.def("update2", &update2, "update2 function");
}
Pythonコード
[1., 2., 3.]
というリストをupdate1
、update2
に渡して、
それぞれの関数適用後にリストがどう変化するのか検証するスクリプトです。
import numpy as np
import hoge
x = [1., 2., 3.]
print(x)
hoge.update1(x)
print(x)
x = np.array(x)
hoge.update2(x)
print(x)
結果
[1.0, 2.0, 3.0]
[1.0, 2.0, 3.0]
[1. 1. 1.]
update1
では値が更新されず、update2
では更新されていることがわかります。
参考リンク先でも説明されていますが、型(今回はdouble)がPython側とC++側で一致しないと
値渡しになってしまうので注意してください。