メインコンテンツまでスキップ
バージョン: 1.1.0

補足事項 - pybind11

Map Scanner では探索処理を高速化するために、pybind11 というライブラリを利用しています。 pybind11 は C++11 を Python からお手軽に取り扱うためのヘッダライブラリです。

本ページでは pybind11 の利用方法を解説します。

開発環境構築

Windows では、Visual Studio 2017 以降のみがサポートされます。 Visual Studio 2017 (MSVC 14.1) で C++17 を使用するには、 pybind11 で標準の準拠を強制 (/permissive-) するためにフラグをコンパイラに渡す必要があります。 Visual Studio 2019 でビルドする場合、厳密には必要ありませんが、設定することを推奨します。

pybind11 のインストール

pybind11 は様々な方法でダウンロードできます。 公式ドキュメントを参考にインストールを実施してください。

Visual Studio の設定

  1. 新しいプロジェクトを作成します。プロジェクト名とソースファイル名が一致する必要があります。
    image
  2. 64 ビットの Python ランタイムの場合は、x64 構成をアクティブにします。
    image
  3. 「プロジェクトの既定値」->「構成の種類」を「ダイナミック ライブラリ (.dll)」に設定します。
    image
  4. 「詳細」->「ターゲットファイル拡張子」を「.pyd」に設定します。
    image
  5. 「C/C++」->「全般」->「追加のインクルードディレクトリ」に、Python と pybind11 の include パスを入力します。
    image
    image
  6. インストールに合わせて、.lib ファイルが含まれる Python の libs フォルダーを追加します。 (例: c:\Python36\libs)
    注意

    .py ファイルが含まれる Lib フォルダ ではなく、必ず .lib ファイルが含まれる libs フォルダーを指定するようにしてください。
    image

これで Visual Studio の環境設定が完了しました。

C++ と Python の連携

  1. 非常に単純な関数の Python バインディングを作成することから始めます。以下は 2 つの数値を加算し、その結果を返す関数の例です。
    image
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(Project1, m) {
m.doc() = "pybind11 test";
m.def("add", &add, "A function that adds two numbers");
}
  1. ビルドします。
    image

  2. 生成した .pyd ファイルを Python プロジェクトのルートディレクトリに配置し、次のコードを入力して起動します。
    image

import Project1
_sum = Project1.add(1,1)
print(_sum)

以上で C++ と Python 連携が出来ました。

なお、Python から C++ で構築されたクラスを直接インスタンス化することもできます。

#include <pybind11/pybind11.h>
namespace py = pybind11;
using namespace std;

int add(int i, int j) {
return i + j;
}

class TestClass
{
float product;
public:
TestClass(float _product) :product(_product){}
float multiplication(float input) {
return input * product;
}
};


PYBIND11_MODULE(Project1, m) {
m.doc() = "pybind11 test";

m.def("add", &add, "A function that adds two numbers");

py::class_<TestClass>(m, "TestClass")
.def(py::init<float>())
.def("multiplication", &TestClass::multiplication)
;
}
import Project1
_sum = Project1.add(1,1)
print(_sum)
cl = Project1.TestClass(2.1)
product = cl.multiplication(0.4)
print(product)

image

配列処理

pybind11 では配列を C++ で操作したり、異なるフォーマットの統一処理を行ったりすることも可能です。

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

template <typename T>
py::array_t<T> modify_array_inplace(py::array_t<T> x, T a)
{
auto k = *x.data(1, 1); // arr 数値の取得
*x.mutable_data(1, 1) = a; // arr 数値の変更
py::print("c_arr:", x); // Python の形で arr を print できる
return x;
}


PYBIND11_MODULE(Project1, m)
{
m.doc() = "pybind11 test";
m.def("modify_array_inplace", &modify_array_inplace<int32_t>, "");
m.def("modify_array_inplace", &modify_array_inplace<float_t>, "");
m.def("modify_array_inplace", &modify_array_inplace<bool>, "");
}
import Project1
import numpy as np

arr = np.zeros((5,5)).astype(int)
_arr = build.modify_array_inplace(arr, 4)
print("p_arr", _arr)

arr = np.zeros((5,5)).astype(bool)
_arr = build.modify_array_inplace(arr, True)
print("p_arr", _arr)

image

参考