Your SlideShare is downloading. ×
0
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Wrapping a C++ library with Cython

4,004

Published on

Published in: Software
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,004
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
29
Comments
0
Likes
7
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Wrapping a C++ library with Cython Tokyo.SciPy #5 2013-01-26 1 / 39
  • 2. 概要 Cython を用いた C/C++ライブラリの Python ラッパー作成 Python/C APIの初歩について説明する. 2 / 39
  • 3. Outline1. Introduction2. Cython3. Python/C API4. Summary 3 / 39
  • 4. 1. Introduction 4 / 39
  • 5. 動機 Python と C/C++の両方の長所を活かしたい C/C++ 実行速度の速さ データ構造, 数値計算ライブラリが揃っている → 計算量が支配的な箇所に使う Python 読み書きしやすさ, 柔軟性, 拡張性, ポータビリティ 利便性の高いライブラリが揃っている → その他のすべての箇所に使う データ収集, 前処理 コマンドライン, GUI アプリ, ウェブアプリ 設定ファイル, ジョブ管理, ログ管理 テスト, 可視化, ドキュメンテーション, · · · ⇒ Python から C/C++を呼び出せればよい 5 / 39
  • 6. 6 / 39
  • 7. Python/C APIPython/C API を用いて Python の拡張モジュールを作成することにより以下が可能となる. 新しいオブジェクトの追加 C/C++の呼び出しhttp://docs.python.jp/2/c-api/index.htmlhttp://docs.python.jp/2/extending/extending.html 7 / 39
  • 8. say.c#include <Python.h>static PyObject* say_hello(PyObject* self, PyObject* args) { const char* name; if (!PyArg_ParseTuple(args, "s", &name)) return NULL; printf("Hello %s!n", name); Py_RETURN_NONE;}...setup.pysetup(name="say", ext_modules=[ Extension("say", ["say.c"])]) 8 / 39
  • 9. $ python setup.py build_ext --inplace$ python>>> import say Python の内部構造についての知識が必要 メモリ管理, 例外処理などが面倒 コード量が多い ⇒ 拡張モジュールを作成するためのツールを使う 9 / 39
  • 10. 拡張モジュールを作成するためのツールC/C++による拡張モジュールを作成するためのツールとして Pyrex Cython SWIG SIP Boost.Pythonなどがある.以下では Cython を用いて C/C++ライブラリの Python ラッパーを作成する方法について説明する. 10 / 39
  • 11. 2. Cython 11 / 39
  • 12. Cython Python の拡張モジュールを作成するための言語 Python + 型宣言を基本とした言語仕様 CPython 2.4-3.x, Windows/Mac/Linux Apache License lxml, Numpy, Scipy, Sage, mpi4py, petsc4py, · · · http://cython.org/ 12 / 39
  • 13. 拡張モジュールの作成方法 1. pyx ファイルを作成する 2. Cython を用いて pyx ファイルを c/cpp ファイルに変換する 3. c/cpp ファイルをコンパイルする生成された so ファイルは Python から直接インポートできる.setup(ext_modules=cythonize("foo.pyx"))$ python setup.py build_ext --inplace$ python>>> import foo 13 / 39
  • 14. Cython では Python のソースコードが (ほぼ) そのまま使えるさらに以下のような言語仕様が加えられている. 型宣言 C/C++の読み込み 条件付きコンパイル コンパイラディレクティブ etc. 14 / 39
  • 15. 型宣言cdef int i, j[10]cdef float f, *gcdef struct Rectangle: float width float heightcdef enum State: open = 1 closed = 2cdef object pyobjctypedef unsigned long uint64_tfrom libc.stdint cimport int64_t 15 / 39
  • 16. 型変換基本的な数値型と文字列型については, Python オブジェクトと C変数が自動変換される.cdef bytes py_byte_stringcdef unicode py_unicode_stringcdef char* c_stringpy_byte_string = <bytes> c_stringpy_byte_string = c_stringpy_byte_string = c_string[:length]c_string = py_byte_stringpy_unicode_string = py_byte_string.decode("utf-8")py_byte_string = py_unicde_string.encode("utf-8") 16 / 39
  • 17. 関数定義def により定義 引数, 返り値ともに Python オブジェクト Python から呼び出せるcdef により定義 引数, 返り値ともに C 変数 (Python オブジェクトも含む) Python から呼び出せないdef integrate(double a, double b, int N): # 引数, 返り値は自動的に型変換される cdef int i cdef double s, dx s = 0; dx = (b - a) / N for i in range(N): s += f(a + i * dx) return s * dxcdef float f(double x) except *: return 1 / x 17 / 39
  • 18. 拡張型cdef class Interval: cdef public float x0, x1 def __init__(self, x0, x1): self.x0 = x0; self.x1 = x1 @property def length(self): return self.x1 - self.x0def widen(Interval i not None, r): i.x0 *= r; i.x1 *= r ビルトイン型, 拡張型を継承できる. 多重継承はできない. アトリビュートには public, readonly を指定できる 拡張型の値は None を取りうる 拡張型の引数には not None を指定できる <MyClass?> は型チェック付きキャスト 18 / 39
  • 19. 拡張型の初期化 cinit C レベルの初期化を行う. 必ず一度だけ呼び出される. この時点では Python オブジェクトとして不完全. init cinit 以外の初期化を行う. 複数回呼ばれる/1 回も呼ばれない場合もある.dealloc C レベルの破棄処理. この時点では Python オブジェクトとして不完全.基底型の cinit が先に呼び出される.コンストラクタに渡した引数は cinit , init の両方に渡される. 19 / 39
  • 20. C 言語とのシンタックスの違い const は使えない ヌルポインタは NULL により表す p->a の代わりに p.a を使う &x の代わりに cython.address(x) を使う *p の代わりに p[0] or cython.operator.dereference(p) を使う 20 / 39
  • 21. C の読み込みCython は C のヘッダファイルを読まないため, 以下のような宣言が必要となる.cdef extern from "math.h": double sin(double) double M_PIdef py_sin(d): # Python から呼び出し可能 return sin(M_PI / 180.0 * d) 21 / 39
  • 22. C++の読み込み 名前空間 クラス テンプレート 演算子オーバーロード ポリモーフィズムなどに対応している.C++の例外は対応する Python の例外に翻訳される. 22 / 39
  • 23. STL コンテナ STL コンテナは libcpp 以下から cimport するだけで使える 対応する Python 組み込み型があれば自動変換されるfrom libcpp.string cimport stringcdef string cpp_stringcdef bytes py_byte_stringcpp_string = <string> py_byte_stringcpp_string = py_byte_stringpy_byte_string = cpp_string 23 / 39
  • 24. C++クラスの宣言pair.pyxcdef extern from "<utility>" namespace "std": cdef cppclass pair[T, U]: T first U second pair() nogil except + pair(pair&) nogil except + pair(T&, U&) nogil except + bint operator==(pair&, pair&) nogil bint operator!=(pair&, pair&) nogil ...cdef pair[int, char*] *p = new pair[int, char*](1, "One")setup.pysetup(ext_modules=cythonize("pair.pyx", language="c++")) 24 / 39
  • 25. Python ラッパークラスcppclass を Python から呼び出すにはラッパークラスが必要.cdef class PyPair: cdef pair[int, char*] *thisptr def __cinit__(self, *args, **kw): self.thisptr = new pair[int, char*]() def __init__(self, int i, char* s): self.thisptr.first = i self.thisptr.second = s def __dealloc__(self): del self.thisptr @property def first(self): return self.thisptr.first @property def second(self): return self.thisptr.second 25 / 39
  • 26. デバッガ $ python-dbg setup.py build_ext --pyrex-gdb --inplace $ cygdb (gdb)使い方は GDB とほぼ同じ. ブレークポイントの設定 スタックのインスペクション ステップ実行 etc. 26 / 39
  • 27. typedness のアノテーションCython および C/C++コードを typedness により色分けした HTMLファイルを生成する. $ cython foo.pyx -a http://docs.cython.org/src/quickstart/cythonize.html 27 / 39
  • 28. プロファイリング次のディレクティブによりプロファイリングが有効になる. # cython: profile=True使用方法は cProfile を使った Python のプロファイリングと同じ.cProfile.runctx("extmod.func()", globals(), locals(), "Profile.prof")s = pstats.Stats("Profile.prof") 28 / 39
  • 29. その他の機能 Numpy との連携 Sage Notebook との連携 コンパイラディレクティブ 条件付きコンパイル 融合型 型つきメモリビュー 並列化 GIL 制御 etc. 詳しくは http://docs.cython.org/ 29 / 39
  • 30. 3. Python/C API 30 / 39
  • 31. Cython により生成された C/C++ファイルを読むには Python/C APIの知識が必要となる. 以下ではその初歩について説明する. 詳しくは http://docs.python.jp/2/extending/index.html 31 / 39
  • 32. すべてのデータはオブジェクト#define PyObject_HEAD _PyObject_HEAD_EXTRA /* デバグ用*/ Py_ssize_t ob_refcnt; /* 参照カウンタ */ struct _typeobject *ob_type; /* 型オブジェクト */typedef struct _object { PyObject_HEAD} PyObject;typedef struct { PyObject_HEAD long ob_ival;} PyIntObject; PyInt FromLong などで Python オブジェクトを構築 PyInt Check などで型チェ ック PyInt AsLong などで C 変数を取得 32 / 39
  • 33. 33 / 39
  • 34. Python から呼び出す関数の引数, 返り値は Python オブジェクトstatic PyObject *func(PyObject *self, PyObject *args) { const char *s; if (!PyArg_ParseTuple(args, "s", &s)) return NULL; ...}typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); PyErr *で例外処理if (PyErr_Occurred()) { if (/* StopIteration だったら */) PyErr_Clear(); else { goto __pyx_error; }} 34 / 39
  • 35. PyObject Call*で Python オブジェクトの呼び出しPyObject* PyObject_Call(PyObject *callable, PyObject *args, PyObject *kw) args, kw のチェック, 再帰の管理などが行われる ガベージコレクションは参照カウント法 参照カウントの振る舞い “参照の所有権” により理解される Py INCREF, Py DECREF で参照カウンタを増減 参照カウンタが 0 になったオブジェクトは破棄される 35 / 39
  • 36. 4. Summary 36 / 39
  • 37. まとめ Cython を使って C/C++ライブラリの Python ラッパーを “手軽に” 作ることが出来る 拡張ライブラリの仕組みを把握するには Python/C API の知識が必要 Cython は C/C++と Python の両方の長所を活かすための 橋渡しとしての役割を果たす 37 / 39
  • 38. References[1] http://docs.python.jp[2] http://docs.cython.org/[3] Cython ユーザメーリングリスト[4] D. S. Seljebotn, Fast numerical computations with Cython, Proceedings of the 8th Python in Science Conference, 2009. 38 / 39
  • 39. fin.Revision: 9176288 (2013-01-25) 39 / 39

×