LoginSignup
1
1

More than 5 years have passed since last update.

Boost.Numpyでnumpy.int32のrvalueコンバータの登録

Last updated at Posted at 2014-01-25

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を引数とする関数を用意します。

mymodule.cpp
#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);
}
Makefile
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数が合わないので当然です。

1
1
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
1
1