6
3

More than 3 years have passed since last update.

pybind11でPythonからC++にリストを参照渡しする

Posted at

はじめに

PythonとC++を連携させることができるpybind11では、
STLコンテナを介することでPythonからC++の関数にリストを渡すことができます。

外部リンク:pybind11を使ってPythonからC++コードを実行する方法

しかしこれは値渡しになるため、更新したリストをPythonで使うにはC++側で返り値にする必要があります。

一方、既存のC++資産を使う場合にはできるだけC++のソースコードに手を加えたくないので、
新たに返り値を設定したり更新のところを書き換えたりしたくないことがあります。

そこで、リストではなくNumpyを介することで、
用途は限定的ではありますが参照渡しができるので共有します。

基本的には以下のリンクで解説されているmutable_dataEigenを使うのがいいと思うのですが、
それ以外にもこんなやり方があるというくらいの内容です。
外部リンクpybind11入門(3) NumPy連携その1
外部リンクpybind11入門(3) NumPy連携その2

注意点

  • pybindのインストール方法、基本的な利用方法は説明しません
  • pybindおよびC++は浅い知識しかないので誤りがありましたらコメントください

C++コード

STLコンテナを介してリストを渡す関数update1()と、Numpyで渡す関数update2()を定義します。
どちらも受け取った配列の値を1.0に更新しようとするものです。

hoge.cpp
#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.]というリストをupdate1update2に渡して、
それぞれの関数適用後にリストがどう変化するのか検証するスクリプトです。

test.py
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++側で一致しないと
値渡しになってしまうので注意してください。

6
3
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
6
3