前回と違うのは,numpy.array には numpy.float64 ではなく,numpy.int64 が入っている点である.しかし.numpy.float64 は,
vec[i] = boost::python::extract< float >(
float32_3_obj.attr("__getitem__")(i));
つまり, boost::python::extract< float >(f) で float 値に変換できた.しかし,numpy.int64を
vec[i] = boost::python::extract< int >(
int32_3_obj.attr("__getitem__")(i));
つまり,boost::python::extract< int >(i) で int 値に変換しようとするとできないのである.そうしようとすると,
TypeError: No registered converter was able to produce a C++ rvalue of
type int from this Python object of type numpy.int64.
というエラーに出会うことになる.これに関しては web を探してみると,http://boost.2283326.n4.nabble.com/extracting-a-numpy-int32-type-td2701573.html という記事があった.どうやら numpy では numpy.float64 から float への converter が register されているのだが,numpy.int64 に関しては 64bit マシンではそういう converter がないようだ.python の世界では int(i) を使えばいいとあるが,C++の世界ではそうはいかない.そこで以下のようなトリックを使う.
int vec[] = {0, 0, 0};
for(int i = 0; i < 3; ++i){
object int64_obj = int32_3_obj.attr("__getitem__")(i);
vec[i] = boost::python::extract< int >(
int64_obj.attr("__int__")());
}
このトリックは一度 numpy.int64 を python の object として取り出し,その attribute にある int への変換メンバを使う.
ここでヒントを一つ.どうやったらそんな変換関数があるのがわかるのだろうか?それは python のオブジェクト自身に尋ねることができる.python の object のattribute はそれ自身 python のシーケンスとして見ることができる.つまり,python の interpreter から, type() を使うと以下のような出力が得られる.
>>> import numpy
>>> a = numpy.array([1,2,3])
>>> type(a[0])
<type 'numpy.int64'>
つまり numpy.array の要素は 'int' ではなく, numpy.int64 であることがわかる.このタイプの object も python の object であるから,どんな attributeを持っているかは, dir()を使えば見ることができる.そうすると,intへの変換が用意されていることがわかる.それを使ってみよう.
>>> type(a[0].__int__())
<type 'int'>
今度は 'int' が取り出せた.この object なら extract< int >で C++ の intが取り出せる.
基本的にここにあるようにすれば,ユーザ側で定義した python の内容を C++に渡すことができる.
この情報が誰かの役に立ったら嬉しいです.