前回はpybind11の簡単なビルド周りを試したので今回はデータ構造(STLコンテナ)を試してみる。公式docによると以下のように自動的にデータ構造のマッピングをやってくれるらしい。
- list <--> std::list, std::vector, std::array
- tuple <--> std::pair, std::tuple
- dict <--> std::map, std::unordered_map
- set <--> std::set, std::unordered_set
- str <--> std::string
ソースコード
今回はPython側からtupleのlistを渡してそれをC++でstd::unordered_mapに変換し、Pythonに戻す関数を作ってみる。
CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(pybind_test VERSION 0.2.0)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(pybind11)
pybind11_add_module(mymodule module.cpp)
module.cpp
#include <utility>
#include <string>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
auto make_dict(const std::vector<std::pair<std::string, int32_t>> &items){
std::unordered_map<std::string, int32_t> d;
for (const auto &item: items){
d[item.first] = item.second;
}
return d;
}
PYBIND11_MODULE(mymodule, m)
{
m.doc() = "my test module";
m.def("make_dict", &make_dict, "");
}
C++側ではstd::vector<std::pair<std::string, int32_t>>
のようにしてPythonで言うList[Tuple[str, int]]
を受け取り、std::unordered_map<std::string, int32_t>
を返すことでPythonのDict[str, int]
に変換される。なお、STLコンテナの自動変換を利用する場合はpybind11/stl.h
が必要。
buildして実行してみるとちゃんとdictが作られる。
import mymodule
mymodule.make_dict([("a", 1), ("b", 2), ("c", 3)])
>> {'c': 3, 'a': 1, 'b': 2}
公式docによると他にも
- datetime <--> std::chrono
- Python func <--> C++ func
- NumPy array <--> Eigen
などの自動変換にも対応しているとのこと。