53
ctype拡張モジュール Moriyoshi Koizumi <[email protected]>

ctypes拡張モジュール

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: ctypes拡張モジュール

ctype拡張モジュールMoriyoshi Koizumi <[email protected]>

Page 2: ctypes拡張モジュール

自己紹介● はてな:moriyoshi● twitter:moriyoshit● 某研究機関で生物シミュレーションの研究をし

ています。● 日々PythonとC++を書いてます!!● 好きなテンプレート言語はPHPです!!!!

Page 3: ctypes拡張モジュール

パーフェクトPHP出ました

Page 4: ctypes拡張モジュール

月刊Python出ます

Page 5: ctypes拡張モジュール

BeepLoudやってます!

Page 6: ctypes拡張モジュール

はい

Page 7: ctypes拡張モジュール

ctypes拡張モジュールとは● Python 2.5より追加● Thomas Heller作● C言語で書かれた共有ライブラリをPythonから

利用するためのライブラリ● 中身はlibffiのラッパー● 複数のOSに対応● といってもピンときませんよね...

Page 8: ctypes拡張モジュール

C言語で書かれた共有ライブラリをPythonから利用するための

ライブラリ

Page 9: ctypes拡張モジュール

それCythonでできるよ● CythonはCython拡張を施されたPythonで書か

れたコードをCに変換する仕組み● 生成されたCのコードをPythonのC拡張にコン

パイルしない限りは利用できない● 開発にはCをコンパイル、リンクする環境が必

要● 配布時にも、各プラットフォーム用のバイナリ

の準備が必要

Page 10: ctypes拡張モジュール

ctypesなら?● 純粋なPythonスクリプトからCの関数を呼び出

せる– コンパイル不要– 配布時のバイナリ同梱も不要

● プロトタイプ作成、C関数のテストコード作成に威力を発揮

Page 11: ctypes拡張モジュール

Show me what it looks like!

import ctypes

# 標準Cライブラリを読み込むdll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")

# ライブラリの関数を呼び出すdll.printf("Hello, %s world!\n", "bucho")

Page 12: ctypes拡張モジュール

基本的な使い方● ctypes.CDLL オブジェクトを、引数として共有

ライブラリ名を渡して生成● ctypesオブジェクトの属性にアクセスすると、

C関数を呼び出すためのラッパー関数が自動的に生成される

● ラッパー関数は普通のPythonの関数として扱える

● ラッパー関数に渡す引数は自動的にCの型に変換される

Page 13: ctypes拡張モジュール

デモ

Page 14: ctypes拡張モジュール

値ラッパー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

実行結果

Page 15: ctypes拡張モジュール

値ラッパーimport ctypes

dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")

dll.printf("%g\n", ctypes.c_double(3.14))

3.14

実行結果

Page 16: ctypes拡張モジュール

値ラッパー● 組み込みのPythonの型とCの型は一対一で対応

していない● Cの型に対応するPython型をctypes側で用意● 明示的に型を指定してC関数を呼び出したい場

合は値ラッパーのオブジェクトを渡すと、最終的に対応するCの型に変換される

Page 17: ctypes拡張モジュール

値ラッパー値ラッパークラス 対応する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 *

など

Page 18: ctypes拡張モジュール

もうちょっと複雑な例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の平方根

Page 19: ctypes拡張モジュール

もうちょっと複雑な例● C関数の戻り値の型は、デフォルトではint型で

あるとみなされる● C関数のシグニチャを指定するときは、

ラッパー関数の以下の属性を指定する。– restype– argtypes

Page 20: ctypes拡張モジュール

ポインタ渡しimport ctypes

dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib")

retval = ctypes.c_int()dll.scanf("%d", ctypes.byref(retval))print retval

Page 21: ctypes拡張モジュール

ポインタ渡し● 引数に指定されたポインタの示す先に戻り値を

返すようなC関数を扱う場合● ctypes.byref()

Page 22: ctypes拡張モジュール

ctypes.POINTER● 任意の型のポインタ型を作る場合は

ctypes.POINTER(型) を呼ぶと、対応するポインタ型が作られる

● ctypes.POINTER(ctypes.c_int) → int *

Page 23: ctypes拡張モジュール

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() 使った方が早いです。

Page 24: ctypes拡張モジュール

構造体● ctypes.Structureクラスを継承したクラスを作る

ことで、Cの構造体に対応したラッパー型を作れる

● _fields_ 属性に (フィールド名, 型) からなるタプルのリストを渡す

Page 25: ctypes拡張モジュール

構造体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)]

Page 26: ctypes拡張モジュール

コールバック関数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))

Page 27: ctypes拡張モジュール

コールバック関数● ctypes.CFUNCTYPE(戻り値の型, [引数の型, 引

数の型...]) を呼び出して、コールバック関数のラッパーオブジェクトを生成する

● ラッパーオブジェクトは、C関数の呼び出し時に、関数ポインタに変換される

Page 28: ctypes拡張モジュール

クロスプラットフォーム● MacのPythonでも● WindowsのPythonでも● Free UnixのPythonでも● それからIronPythonでも

Page 29: ctypes拡張モジュール

複数プラットフォームをサポートするときの注意点

● たとえば標準C関数のライブラリ名はプラットフォームごとに違う

● sys.platform などでOSを判定して対処

Page 30: ctypes拡張モジュール

まとめ● dll = ctypes.CDLL()で読み込み● dll.[関数名]() で関数を呼び出す● 関数のシグニチャを指定したい場合はrestypeと

argtypes● ラッパー型 c_*● ポインタ渡しは ctypes.byref()● 構造体は ctypes.Structure● コールバック関数は ctypes.CFUNCTYPE()

Page 31: ctypes拡張モジュール

ご清聴ありがとうございました

Page 32: ctypes拡張モジュール

はい

Page 33: ctypes拡張モジュール

始まって

Page 34: ctypes拡張モジュール

しまいました

Page 35: ctypes拡張モジュール

すべらない話

Page 36: ctypes拡張モジュール

PSP®Go

Page 37: ctypes拡張モジュール

値下げしました

Page 38: ctypes拡張モジュール

さて

Page 39: ctypes拡張モジュール

P○P Go

Page 40: ctypes拡張モジュール

○の中に入る文字は?

Page 41: ctypes拡張モジュール

1.H2.S3.P

Page 42: ctypes拡張モジュール

はい

Page 43: ctypes拡張モジュール

1. PHP

Page 44: ctypes拡張モジュール

ですね

Page 45: ctypes拡張モジュール

PHP Go

Page 46: ctypes拡張モジュール

世の中

Page 47: ctypes拡張モジュール

見渡せば

Page 48: ctypes拡張モジュール

Pythonばかり

Page 49: ctypes拡張モジュール

PHPに日の目を

Page 50: ctypes拡張モジュール

はい

Page 51: ctypes拡張モジュール

PHP in Python

Page 52: ctypes拡張モジュール

プロジェクト始動

Page 53: ctypes拡張モジュール

http://bitbucket.org/moriyoshi/php-in-python