2014年2月28日金曜日

ctypesによるarrayの受け渡し

計算処理時間がpythonを使っていると問題になることがあります。
pythonはスクリプト言語なので仕方ないといえばそれまでですが、一部分だけでもC言語で書いて実行形式で計算したいと思うことがあります。
ただ、そう思うのが、開発を始めた頃ではなく、開発がほとんど終盤に差し掛かった頃で、移行が簡単ではないことが多いです。

自作class やscipyやnumpyを使い、引数をやりとりしていると、簡単には置き換えしにくくなります。
今回はnumpyのctypesを使ってnumpy.arrayを引数として渡す方法についてまとめてみます。

手順は

  1. c言語でダイナミックリンクライブラリを作ります
  2. pythonプログラムでライブラリを読み込む設定を書き込みます
    1. load_libraryで読み込み
    2. 引数の型設定
    3. 戻り値の型設定
    4. テスト

という感じです。



C言語によるダイナミックリンクライブラリ作成
arrayで渡したい部分は配列にします。
たとえば
double[] hoge( double x[], int n ){
...
}

と言う感じです。
ファイル名はここでは、libhoge.soと言う名前でつくります。
ウィンドウズの場合は拡張子dllにする必要があります。
gccの場合、
 gcc -shared hoge.c -o libhoge.so
とします。


2.1 python側
ダイナミックリンク読み込み
dll = numpy.ctypeslib.load_library( 'libhoge.so', '.' )
通常ctypesというライブラリが標準でついているのそちらを使っていますが、numpyのctypeslibはarrayを使うときに便利です。
numpyの場合、実行ディレクトリを指定する必要があります。


2.2. 引数型の設定
ndtype = numpy.ctypeslib.ndpointer( dtype=numpy.float64, ndim=1, flags='C_CONTIGUOUS' )
dll.hoge.argtypes = [ ndtype, numpy.ctypeslib.ct.c_int,  ]


2.3.戻り値型指定
dll.hoge.restype = numpy.ctypeslib.ndpointer( dtype=numpy.float64, shape=(100,), flags='C_CONTIGUOUS' )


2.4 実行テスト
x = dll.hoge( numpy.array([ 0.1, 0.3, 0.5],dtype=float), 3 )
として実行してみます。
これでxがnumpy.arrayになっていればOKです。


2.2や2.3の型の設定がややこしいところです。



0 件のコメント:

コメントを投稿