pythonからC++の関数を呼び出したときにnumpy.int32がdid not match C++ signatureになる問題の解決
Boost.Numpyにrvalueコンバータが不足しているので、それを登録する。
コンバータの不足はBoost.Numpyに限らないと思うので、以下の要領で追加すれば、解決できるはずです。
※追記(2014/08/11)
本家のBoost.Numpyが更新されていたり、boostのバージョンが更新されたので、少し書き直しました。
64bit, Visual Studio 2013, numpy-1.8.1で警告が出ないようにいろいろ修正すると変更箇所が多くなったので、forkしました。
64bit, Visual Studio 2013, python3.4(anaconda)でcmakeを利用した環境で付属のテストコードがパスすることを確認しています。
※追記(2014/10/29)
以前からの懸案事項であった、intかlongのどちらかしか使えない問題の解決方法を見つけたので、更新しました。
新しい方法の方がうまくできています。
以前のものとは違う方法で、もはや関係がないので、コードは削除しました。(以前の解決方法が気になる方は、リポジトリよりlib/numpy/src/dtype.cppの以前のバージョンを参照してください)
動作確認
確認用のコード(C++でpythonを拡張する(Boost.NumPy)にあったものを少し変更)
unsigned intとunsigned longを引数とする関数を用意します。
#include "boost/numpy.hpp"
namespace p = boost::python;
namespace np = boost::numpy;
np::ndarray new_zero(unsigned int N) {
p::tuple shape = p::make_tuple(N);
np::dtype dtype = np::dtype::get_builtin<double>();
return np::zeros(shape, dtype);
}
np::ndarray new_empty(unsigned long N) {
p::tuple shape = p::make_tuple(N);
np::dtype dtype = np::dtype::get_builtin<double>();
return np::empty(shape, dtype);
}
BOOST_PYTHON_MODULE(mymodule) {
Py_Initialize();
np::initialize();
p::def("new_zero", new_zero);
p::def("new_empty", new_empty);
}
BOOST_INC=C:/boost
BOOST_LIB=$(BOOST_INC)/stage/lib
BOOST_NUMPY_INC=C:/Boost.NumPy
BOOST_NUMPY_LIB=$(BOOST_NUMPY_INC)/lib/Release
PYTHONHOME=C:/Python34
PYTHON_INC=$(PYTHONHOME)/include
PYTHON_LIB=$(PYTHONHOME)/libs
mymodule.pyd : mymodule.obj
link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:$(BOOST_LIB) /LIBPATH:$(BOOST_NUMPY_LIB) /LIBPATH:$(PYTHON_LIB) mymodule.obj boost_numpy.lib /OUT:mymodule.pyd /IMPLIB:mymodule.lib
mymodule.obj : mymodule.cpp
cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -I$(BOOST_INC) -I$(BOOST_NUMPY_INC) -I$(PYTHON_INC) /Tpmymodule.cpp /Fomymodule.obj /EHsc
実行
In [1]: import numpy as np
In [2]: import mymodule
In [3]: mymodule.new_zero(np.uint32(3))
Out[3]: array([ 0., 0., 0.])
In [4]: mymodule.new_empty(np.uint32(4))
Out[4]:
array([ 2.47959055e-315, 2.47856790e-315, 3.83525216e-316,
4.36620001e-316])
numpy.uint32がunsigned intとunsigned longに変換されているのが分かるかと思います。
ちなみに、numpy.uint64を渡すとエラーになります。bit数が合わないので当然です。