View
5.194
Download
2
Category
Preview:
DESCRIPTION
Citation preview
ctype拡張モジュールMoriyoshi Koizumi <mozo@mozo.jp>
自己紹介● はてな:moriyoshi● twitter:moriyoshit● 某研究機関で生物シミュレーションの研究をし
ています。● 日々PythonとC++を書いてます!!● 好きなテンプレート言語はPHPです!!!!
パーフェクトPHP出ました
月刊Python出ます
BeepLoudやってます!
はい
ctypes拡張モジュールとは● Python 2.5より追加● Thomas Heller作● C言語で書かれた共有ライブラリをPythonから
利用するためのライブラリ● 中身はlibffiのラッパー● 複数のOSに対応● といってもピンときませんよね...
C言語で書かれた共有ライブラリをPythonから利用するための
ライブラリ
それCythonでできるよ● CythonはCython拡張を施されたPythonで書か
れたコードをCに変換する仕組み● 生成されたCのコードをPythonのC拡張にコン
パイルしない限りは利用できない● 開発にはCをコンパイル、リンクする環境が必
要● 配布時にも、各プラットフォーム用のバイナリ
の準備が必要
ctypesなら?● 純粋なPythonスクリプトからCの関数を呼び出
せる– コンパイル不要– 配布時のバイナリ同梱も不要
● プロトタイプ作成、C関数のテストコード作成に威力を発揮
Show me what it looks like!
import ctypes
# 標準Cライブラリを読み込むdll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
# ライブラリの関数を呼び出すdll.printf("Hello, %s world!\n", "bucho")
基本的な使い方● ctypes.CDLL オブジェクトを、引数として共有
ライブラリ名を渡して生成● ctypesオブジェクトの属性にアクセスすると、
C関数を呼び出すためのラッパー関数が自動的に生成される
● ラッパー関数は普通のPythonの関数として扱える
● ラッパー関数に渡す引数は自動的にCの型に変換される
デモ
値ラッパーimport ctypes
dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
dll.printf("%g\n", 3.14)
Traceback (most recent call last): File <stdin>, line 3, in <module> dll.printf("%g\n", 3.14)ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to convert parameter 2
実行結果
値ラッパーimport ctypes
dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
dll.printf("%g\n", ctypes.c_double(3.14))
3.14
実行結果
値ラッパー● 組み込みのPythonの型とCの型は一対一で対応
していない● Cの型に対応するPython型をctypes側で用意● 明示的に型を指定してC関数を呼び出したい場
合は値ラッパーのオブジェクトを渡すと、最終的に対応するCの型に変換される
値ラッパー値ラッパークラス 対応するCの型c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong
char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long
c_foat, c_double, c_longdouble
foat, double, long double
c_char_p, c_wchar_p char *, wchar_t*c_void_p void *
など
もうちょっと複雑な例import ctypes
# 標準Cライブラリを読み込むdll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
# ライブラリの関数を呼び出すdll.getcwd.restype = ctypes.c_char_pprint dll.getcwd() # 現在の作業ディレクトリ
dll.sqrt.restype = ctypes.c_doubledll.sqrt.argtypes = (ctypes.c_double, )print dll.sqrt(16) # 16の平方根
もうちょっと複雑な例● C関数の戻り値の型は、デフォルトではint型で
あるとみなされる● C関数のシグニチャを指定するときは、
ラッパー関数の以下の属性を指定する。– restype– argtypes
ポインタ渡しimport ctypes
dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
retval = ctypes.c_int()dll.scanf("%d", ctypes.byref(retval))print retval
ポインタ渡し● 引数に指定されたポインタの示す先に戻り値を
返すようなC関数を扱う場合● ctypes.byref()
ctypes.POINTER● 任意の型のポインタ型を作る場合は
ctypes.POINTER(型) を呼ぶと、対応するポインタ型が作られる
● ctypes.POINTER(ctypes.c_int) → int *
ctypes.POINTER
import ctypes
c_int_p = ctypes.POINTER(ctypes.c_int)
dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")
retval = ctypes.c_int()dll.scanf("%d", c_int_p(retval))print retval
※このケースだと、ctypes.byref() 使った方が早いです。
構造体● ctypes.Structureクラスを継承したクラスを作る
ことで、Cの構造体に対応したラッパー型を作れる
● _fields_ 属性に (フィールド名, 型) からなるタプルのリストを渡す
構造体struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; char *tm_zone; long tm_gmtoff; };
class TMStructure(ctypes.Structure): _fields_ = [ ('tm_sec', ctypes.c_int), ('tm_min', ctypes.c_int), ('tm_hour', ctypes.c_int), ('tm_mday', ctypes.c_int), ('tm_mon', ctypes.c_int), ('tm_year', ctypes.c_int), ('tm_wday', ctypes.c_int), ('tm_yday', ctypes.c_int), ('tm_isdst', ctypes.c_int), ('tm_zone', ctypes.c_char_p), ('tm_gmtoff', ctypes.c_long)]
コールバック関数void call_callback(void(*cb)(const char *)){ cb("hoge");}
import ctypes
dll = ctypes.CDLL("libcallback.dylib")
cfun = ctypes.CFUNCTYPE(None, ctypes.c_char_p)
def callback(string): print "Hello, %s world!" % string
dll.call_callback(cfun(callback))
コールバック関数● ctypes.CFUNCTYPE(戻り値の型, [引数の型, 引
数の型...]) を呼び出して、コールバック関数のラッパーオブジェクトを生成する
● ラッパーオブジェクトは、C関数の呼び出し時に、関数ポインタに変換される
クロスプラットフォーム● MacのPythonでも● WindowsのPythonでも● Free UnixのPythonでも● それからIronPythonでも
複数プラットフォームをサポートするときの注意点
● たとえば標準C関数のライブラリ名はプラットフォームごとに違う
● sys.platform などでOSを判定して対処
まとめ● dll = ctypes.CDLL()で読み込み● dll.[関数名]() で関数を呼び出す● 関数のシグニチャを指定したい場合はrestypeと
argtypes● ラッパー型 c_*● ポインタ渡しは ctypes.byref()● 構造体は ctypes.Structure● コールバック関数は ctypes.CFUNCTYPE()
ご清聴ありがとうございました
はい
始まって
しまいました
すべらない話
PSP®Go
値下げしました
さて
P○P Go
○の中に入る文字は?
1.H2.S3.P
はい
1. PHP
ですね
PHP Go
世の中
見渡せば
Pythonばかり
PHPに日の目を
はい
PHP in Python
プロジェクト始動
http://bitbucket.org/moriyoshi/php-in-python
Recommended