この記事は
札幌C++勉強会のオンラインもくもく会#36でやった内容をメモります。
インストール方法
他所をあたってください。がんばれ。
やること
簡単な例として、Pythonのnumpyで用意した2次元配列の和を
C++のEigenライブラリを使って計算し、それをまたPythonに返す、ということをします。
C++のソースコード
cpplib.cpp
#define EIGEN_DEFAULT_TO_ROW_MAJOR
#include<Eigen/Core>
#include<boost/numpy.hpp>
namespace py = boost::python;
namespace np = boost::numpy;
np::ndarray add_double(const np::ndarray lhs, const np::ndarray rhs) {
using Stride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
const auto
lrows = lhs.shape(0),
lcols = lhs.shape(1),
rrows = rhs.shape(0),
rcols = rhs.shape(1);
const Stride
lstride(lhs.strides(0)/sizeof(double), lhs.strides(1)/sizeof(double)),
rstride(rhs.strides(0)/sizeof(double), rhs.strides(1)/sizeof(double));
const Eigen::Map<const Eigen::MatrixXd, Eigen::Unaligned, Stride>
lmat(reinterpret_cast<double*>(lhs.get_data()), lrows, lcols, lstride),
rmat(reinterpret_cast<double*>(rhs.get_data()), rrows, rcols, rstride);
np::ndarray ret = np::empty(
py::make_tuple(lmat.rows(),lmat.cols()),
np::dtype::get_builtin<double>());
Eigen::Map<Eigen::MatrixXd>
ret_mat(reinterpret_cast<double*>(ret.get_data()), lmat.rows(), lmat.cols());
ret_mat = lmat + rmat;
return ret;
}
BOOST_PYTHON_MODULE(cpplib) {
Py_Initialize();
np::initialize();
py::def("add_double",add_double);
}
行列の足し算を目的にするだけならもっと簡単に書けるかもしれませんが、応用が効くように書いてます。型が double
限定なのは仕方ないです。やるとしたらdtype
調べて分岐ですが、実行時判定するしかない。
コンパイル方法
SConsでやります。例えばこんなかんじです。mingw環境でやってます。
SConstruct
# vim: filetype=python
# SConstruct
env = Environment(
SHLIBPREFIX="",
SHLIBSUFFIX=".pyd",
CXX="/mingw64/bin/g++",
CXXFLAGS=["-std=c++14"],
LINKFLAGS=["-std=c++14"],
CPPPATH=[
"/mingw64/include/eigen3",
"/mingw64/include/python3.5m", ],
LIBPATH=["/mingw64/lib"])
env.SharedLibrary("cpplib", ["cpplib.cpp"],
LIBS=["boost_numpy", "python3.5.dll", "boost_python3-mt"])
Pythonコード
usecpp.py
import numpy as np
from cpplib import add_double
a = np.array(
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 1, 2, 3],
[4, 5, 6, 7], ], dtype=np.float64)
b = np.array(
[[5, 6],
[4, 5], ], dtype=np.float64)
result = add_double(a[1::2, 1::2], b[::1, ::1])
print(result)
結果は
[[6,8],[5,7]]
と[[5,6],[4,5]]
が足されるので
$ python3 usecpp.py
[[ 11. 14.]
[ 9. 12.]]
となります。ここでもくもく会時間切れ。
追記