ctypes拡張モジュール

6,985 views

Published on

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,985
On SlideShare
0
From Embeds
0
Number of Embeds
1,605
Actions
Shares
0
Downloads
22
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

ctypes拡張モジュール

  1. 1. ctype拡張モジュール Moriyoshi Koizumi <mozo@mozo.jp>
  2. 2. 自己紹介 ● はてな:moriyoshi ● twitter:moriyoshit ● 某研究機関で生物シミュレーションの研究をし ています。 ● 日々PythonとC++を書いてます!! ● 好きなテンプレート言語はPHPです!!!!
  3. 3. パーフェクトPHP出ました
  4. 4. 月刊Python出ます
  5. 5. BeepLoudやってます!
  6. 6. はい
  7. 7. ctypes拡張モジュールとは ● Python 2.5より追加 ● Thomas Heller作 ● C言語で書かれた共有ライブラリをPythonから 利用するためのライブラリ ● 中身はlibffiのラッパー ● 複数のOSに対応 ● といってもピンときませんよね...
  8. 8. C言語で書かれた共有ライブラリを Pythonから利用するための ライブラリ
  9. 9. それCythonでできるよ ● CythonはCython拡張を施されたPythonで書か れたコードをCに変換する仕組み ● 生成されたCのコードをPythonのC拡張にコン パイルしない限りは利用できない ● 開発にはCをコンパイル、リンクする環境が必 要 ● 配布時にも、各プラットフォーム用のバイナリ の準備が必要
  10. 10. ctypesなら? ● 純粋なPythonスクリプトからCの関数を呼び出 せる – コンパイル不要 – 配布時のバイナリ同梱も不要 ● プロトタイプ作成、C関数のテストコード作成 に威力を発揮
  11. 11. Show me what it looks like! import ctypes # 標準Cライブラリを読み込む dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib") # ライブラリの関数を呼び出す dll.printf("Hello, %s world!n", "bucho")
  12. 12. 基本的な使い方 ● ctypes.CDLL オブジェクトを、引数として共有 ライブラリ名を渡して生成 ● ctypesオブジェクトの属性にアクセスすると、 C関数を呼び出すためのラッパー関数が自動的 に生成される ● ラッパー関数は普通のPythonの関数として扱え る ● ラッパー関数に渡す引数は自動的にCの型に変 換される
  13. 13. デモ
  14. 14. 値ラッパー import ctypes dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib") dll.printf("%gn", 3.14) Traceback (most recent call last): File <stdin>, line 3, in <module> dll.printf("%gn", 3.14) ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to convert parameter 2 実行結果
  15. 15. 値ラッパー import ctypes dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib") dll.printf("%gn", ctypes.c_double(3.14)) 3.14 実行結果
  16. 16. 値ラッパー ● 組み込みのPythonの型とCの型は一対一で対応 していない ● Cの型に対応するPython型をctypes側で用意 ● 明示的に型を指定してC関数を呼び出したい場 合は値ラッパーのオブジェクトを渡すと、最終 的に対応するCの型に変換される
  17. 17. 値ラッパー 値ラッパークラス 対応する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 * など
  18. 18. もうちょっと複雑な例 import ctypes # 標準Cライブラリを読み込む dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib") # ライブラリの関数を呼び出す dll.getcwd.restype = ctypes.c_char_p print dll.getcwd() # 現在の作業ディレクトリ dll.sqrt.restype = ctypes.c_double dll.sqrt.argtypes = (ctypes.c_double, ) print dll.sqrt(16) # 16の平方根
  19. 19. もうちょっと複雑な例 ● C関数の戻り値の型は、デフォルトではint型で あるとみなされる ● C関数のシグニチャを指定するときは、 ラッパー関数の以下の属性を指定する。 – restype – argtypes
  20. 20. ポインタ渡し import ctypes dll = ctypes.CDLL("/usr/lib/libSystem.B.dylib") retval = ctypes.c_int() dll.scanf("%d", ctypes.byref(retval)) print retval
  21. 21. ポインタ渡し ● 引数に指定されたポインタの示す先に戻り値を 返すようなC関数を扱う場合 ● ctypes.byref()
  22. 22. ctypes.POINTER ● 任意の型のポインタ型を作る場合は ctypes.POINTER(型) を呼ぶと、対応するポイ ンタ型が作られる ● ctypes.POINTER(ctypes.c_int) → int *
  23. 23. 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() 使った方が早いです。
  24. 24. 構造体 ● ctypes.Structureクラスを継承したクラスを作る ことで、Cの構造体に対応したラッパー型を作 れる ● _fields_ 属性に (フィールド名, 型) からなるタ プルのリストを渡す
  25. 25. 構造体 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)]
  26. 26. コールバック関数 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))
  27. 27. コールバック関数 ● ctypes.CFUNCTYPE(戻り値の型, [引数の型, 引 数の型...]) を呼び出して、コールバック関数の ラッパーオブジェクトを生成する ● ラッパーオブジェクトは、C関数の呼び出し時 に、関数ポインタに変換される
  28. 28. クロスプラットフォーム ● MacのPythonでも ● WindowsのPythonでも ● Free UnixのPythonでも ● それからIronPythonでも
  29. 29. 複数プラットフォームを サポートするときの注意点 ● たとえば標準C関数のライブラリ名はプラット フォームごとに違う ● sys.platform などでOSを判定して対処
  30. 30. まとめ ● dll = ctypes.CDLL()で読み込み ● dll.[関数名]() で関数を呼び出す ● 関数のシグニチャを指定したい場合はrestypeと argtypes ● ラッパー型 c_* ● ポインタ渡しは ctypes.byref() ● 構造体は ctypes.Structure ● コールバック関数は ctypes.CFUNCTYPE()
  31. 31. ご清聴ありがとうございました
  32. 32. はい
  33. 33. 始まって
  34. 34. しまいました
  35. 35. すべらない話
  36. 36. PSP® Go
  37. 37. 値下げしました
  38. 38. さて
  39. 39. P○P Go
  40. 40. ○の中に 入る文字は?
  41. 41. 1.H 2.S 3.P
  42. 42. はい
  43. 43. 1. PHP
  44. 44. ですね
  45. 45. PHP Go
  46. 46. 世の中
  47. 47. 見渡せば
  48. 48. Pythonばかり
  49. 49. PHPに日の目を
  50. 50. はい
  51. 51. PHP in Python
  52. 52. プロジェクト始動
  53. 53. http://bitbucket.org/moriyoshi/php-in-python

×