ラベル ctypes の投稿を表示しています。 すべての投稿を表示
ラベル ctypes の投稿を表示しています。 すべての投稿を表示

2014年3月17日月曜日

C言語との連携 ctypes


pythonは高機能で大変便利ですが、処理が遅いので困る場合があります。
そういう場合は、いろいろと工夫して高速化する方法があります。

ctypesによるDLLの利用はその高速化手法の一つです。
つまり、C言語(など)でDLLを作成して、pythonから読み込みます。
そのDLLを呼びだすためのライブラリがctypesです。

import ctypes

d = ctypes.cdll.LoadLibrary("libx.dll")


C言語と言いましたが、実際C++で作成しても構いません。
但し、呼びだす関数部分はC言語の方式で書かなければなりません。

つまり裏側ではC++のclass定義やインスタンスを生成しても構いませんが、
pythonから呼び出す部分は

extern "C"

などとしてC言語方式で、関数にしなければならないということです。




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の型の設定がややこしいところです。