SlideShare a Scribd company logo
Wrapping a C++ library with Cython



            Tokyo.SciPy #5
              2013-01-26




                                     1 / 39
概要




  Cython を用いた C/C++ライブラリの Python ラッパー作成
  Python/C API
の初歩について説明する.




                                      2 / 39
Outline


1.   Introduction


2.   Cython


3.   Python/C API


4.   Summary




                    3 / 39
1. Introduction




                  4 / 39
動機
     Python と C/C++の両方の長所を活かしたい

 C/C++ 実行速度の速さ
        データ構造, 数値計算ライブラリが揃っている
                   → 計算量が支配的な箇所に使う
 Python 読み書きしやすさ, 柔軟性, 拡張性, ポータビリティ
        利便性の高いライブラリが揃っている
                   → その他のすべての箇所に使う
        データ収集, 前処理
        コマンドライン, GUI アプリ, ウェブアプリ
        設定ファイル, ジョブ管理, ログ管理
        テスト, 可視化, ドキュメンテーション, · · ·

 ⇒ Python から C/C++を呼び出せればよい
                                      5 / 39
6 / 39
Python/C API


Python/C API を用いて Python の拡張モジュールを作成することに
より以下が可能となる.
   新しいオブジェクトの追加
   C/C++の呼び出し



http://docs.python.jp/2/c-api/index.html
http://docs.python.jp/2/extending/extending.html




                                                   7 / 39
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.py

setup(name="say", ext_modules=[
   Extension("say", ["say.c"])
])

                                                       8 / 39
$ python setup.py build_ext --inplace
$ python
>>> import say



  Python の内部構造についての知識が必要
  メモリ管理, 例外処理などが面倒
  コード量が多い

 ⇒ 拡張モジュールを作成するためのツールを使う




                                        9 / 39
拡張モジュールを作成するためのツール

C/C++による拡張モジュールを作成するためのツールとして
  Pyrex
  Cython
  SWIG
  SIP
  Boost.Python
などがある.

以下では Cython を用いて C/C++ライブラリの Python ラッパーを
作成する方法について説明する.



                                      10 / 39
2. Cython




            11 / 39
Cython



   Python の拡張モジュールを作成するための言語
   Python + 型宣言を基本とした言語仕様
   CPython 2.4-3.x, Windows/Mac/Linux
   Apache License
   lxml, Numpy, Scipy, Sage, mpi4py, petsc4py, · · ·
   http://cython.org/




                                                       12 / 39
拡張モジュールの作成方法
 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
Cython では Python のソースコードが (ほぼ) そのまま使える

さらに以下のような言語仕様が加えられている.
  型宣言
  C/C++の読み込み
  条件付きコンパイル
  コンパイラディレクティブ
  etc.




                                     14 / 39
型宣言


cdef int i, j[10]
cdef float f, *g
cdef struct Rectangle:
    float width
    float height
cdef enum State:
    open = 1
    closed = 2
cdef object pyobj
ctypedef unsigned long uint64_t
from libc.stdint cimport int64_t




                                   15 / 39
型変換
基本的な数値型と文字列型については, Python オブジェクトと C
変数が自動変換される.

cdef bytes py_byte_string
cdef unicode py_unicode_string
cdef char* c_string

py_byte_string = <bytes> c_string
py_byte_string = c_string
py_byte_string = c_string[:length]
c_string = py_byte_string

py_unicode_string = py_byte_string.decode("utf-8")
py_byte_string = py_unicde_string.encode("utf-8")



                                                     16 / 39
関数定義
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 * dx
cdef float f(double x) except *:
    return 1 / x
                                            17 / 39
拡張型
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.x0
def widen(Interval i not None, r):
    i.x0 *= r; i.x1 *= r


    ビルトイン型, 拡張型を継承できる. 多重継承はできない.
    アトリビュートには public, readonly を指定できる
    拡張型の値は None を取りうる
    拡張型の引数には not None を指定できる
    <MyClass?> は型チェック付きキャスト
                                     18 / 39
拡張型の初期化

 cinit   C レベルの初期化を行う.
         必ず一度だけ呼び出される.
         この時点では Python オブジェクトとして不完全.
  init   cinit 以外の初期化を行う.
        複数回呼ばれる/1 回も呼ばれない場合もある.
dealloc C レベルの破棄処理.
        この時点では Python オブジェクトとして不完全.
基底型の cinit が先に呼び出される.
コンストラクタに渡した引数は cinit ,    init の両方に渡さ
れる.



                                   19 / 39
C 言語とのシンタックスの違い



 const は使えない
 ヌルポインタは NULL により表す
 p->a の代わりに p.a を使う
 &x の代わりに cython.address(x) を使う
 *p の代わりに p[0] or cython.operator.dereference(p)
 を使う




                                             20 / 39
C の読み込み


Cython は C のヘッダファイルを読まないため, 以下のような宣言
が必要となる.

cdef extern from "math.h":
    double sin(double)
    double M_PI

def py_sin(d):
    # Python から呼び出し可能
    return sin(M_PI / 180.0 * d)




                                   21 / 39
C++の読み込み


  名前空間
  クラス
  テンプレート
  演算子オーバーロード
  ポリモーフィズム
などに対応している.

C++の例外は対応する Python の例外に翻訳される.




                                22 / 39
STL コンテナ


    STL コンテナは libcpp 以下から cimport するだけで使える
    対応する Python 組み込み型があれば自動変換される

from libcpp.string cimport string
cdef string cpp_string
cdef bytes py_byte_string

cpp_string = <string> py_byte_string
cpp_string = py_byte_string
py_byte_string = cpp_string




                                       23 / 39
C++クラスの宣言
pair.pyx

cdef 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.py

setup(ext_modules=cythonize("pair.pyx", language="c++"))

                                                      24 / 39
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
デバッガ


 $ python-dbg setup.py build_ext --pyrex-gdb --inplace
 $ cygdb
 (gdb)

使い方は GDB とほぼ同じ.
   ブレークポイントの設定
   スタックのインスペクション
   ステップ実行
   etc.




                                                     26 / 39
typedness のアノテーション
Cython および C/C++コードを typedness により色分けした HTML
ファイルを生成する.

 $ cython foo.pyx -a




        http://docs.cython.org/src/quickstart/cythonize.html


                                                               27 / 39
プロファイリング


次のディレクティブによりプロファイリングが有効になる.

 # cython: profile=True

使用方法は cProfile を使った Python のプロファイリングと同じ.

cProfile.runctx("extmod.func()",
                globals(), locals(), "Profile.prof")
s = pstats.Stats("Profile.prof")




                                                       28 / 39
その他の機能
 Numpy との連携
 Sage Notebook との連携
 コンパイラディレクティブ
 条件付きコンパイル
 融合型
 型つきメモリビュー
 並列化
 GIL 制御
 etc.


                  詳しくは http://docs.cython.org/


                                         29 / 39
3. Python/C API




                  30 / 39
Cython により生成された C/C++ファイルを読むには Python/C API
の知識が必要となる. 以下ではその初歩について説明する.


 詳しくは http://docs.python.jp/2/extending/index.html




                                             31 / 39
すべてのデータはオブジェクト
#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 / 39
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
PyObject Call*で Python オブジェクトの呼び出し

PyObject* PyObject_Call(PyObject *callable,
                        PyObject *args, PyObject *kw)


    args, kw のチェック, 再帰の管理などが行われる


           ガベージコレクションは参照カウント法

    参照カウントの振る舞い “参照の所有権” により理解される
    Py INCREF, Py DECREF で参照カウンタを増減
    参照カウンタが 0 になったオブジェクトは破棄される


                                                        35 / 39
4. Summary




             36 / 39
まとめ


 Cython を使って C/C++ライブラリの Python ラッパーを
 “手軽に” 作ることが出来る
 拡張ライブラリの仕組みを把握するには
 Python/C API の知識が必要


                    Cython は
      C/C++と Python の両方の長所を活かすための
            橋渡しとしての役割を果たす




                                        37 / 39
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
fin.




Revision: 9176288 (2013-01-25)

                                       39 / 39

More Related Content

PDF
Optimizer入門&最新動向
PDF
TensorFlow XLAは、 中で何をやっているのか?
PPTX
C#とILとネイティブと
PDF
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
PDF
Rust で RTOS を考える
PDF
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
PDF
いまさら恥ずかしくてAsyncをawaitした
PDF
Constexpr 中3女子テクニック
Optimizer入門&最新動向
TensorFlow XLAは、 中で何をやっているのか?
C#とILとネイティブと
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Rust で RTOS を考える
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
いまさら恥ずかしくてAsyncをawaitした
Constexpr 中3女子テクニック

What's hot (20)

PDF
いまさら聞けないarmを使ったNEONの基礎と活用事例
PDF
組み込み関数(intrinsic)によるSIMD入門
PDF
プログラミングコンテストでの動的計画法
PPTX
TVMの次期グラフIR Relayの紹介
PDF
マーク&スイープ勉強会
PDF
Vivado hls勉強会1(基礎編)
PDF
PyQtではじめるGUIプログラミング
PDF
Rの高速化
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
Marp Tutorial
PDF
いまさら聞けない!CUDA高速化入門
PDF
3次元レジストレーション(PCLデモとコード付き)
PDF
できる!並列・並行プログラミング
PPTX
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
PPTX
Visual Studio CodeでRを使う
PDF
[DL輪読会]SlowFast Networks for Video Recognition
PDF
NumPyが物足りない人へのCython入門
PDF
【プレゼン】見やすいプレゼン資料の作り方【初心者用】
PDF
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
PPTX
RustによるGPUプログラミング環境
いまさら聞けないarmを使ったNEONの基礎と活用事例
組み込み関数(intrinsic)によるSIMD入門
プログラミングコンテストでの動的計画法
TVMの次期グラフIR Relayの紹介
マーク&スイープ勉強会
Vivado hls勉強会1(基礎編)
PyQtではじめるGUIプログラミング
Rの高速化
ネットワーク ゲームにおけるTCPとUDPの使い分け
Marp Tutorial
いまさら聞けない!CUDA高速化入門
3次元レジストレーション(PCLデモとコード付き)
できる!並列・並行プログラミング
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
Visual Studio CodeでRを使う
[DL輪読会]SlowFast Networks for Video Recognition
NumPyが物足りない人へのCython入門
【プレゼン】見やすいプレゼン資料の作り方【初心者用】
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
RustによるGPUプログラミング環境
Ad

Viewers also liked (20)

PPT
No te comas la coma
PDF
Scalaと過ごした5ヶ月間
PPTX
Hpcビジネスコンテンスト発表資料
KEY
Pythonについて
PDF
Pythonおじさんのweb2py挑戦記
PDF
ScalaでAndroidアプリ開発
PPTX
Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話
PDF
Scala 初めての人が Heroku で Web アプリを公開するまで
PDF
多分モダンなWebアプリ開発
PDF
Pythonの開発環境を調べてみた
PPTX
数理最適化とPython
PDF
めんどくさくない Scala #kwkni_scala
PDF
コンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashi
PDF
ヒカルのGo 資料 Webアプリケーションの作り方
PDF
Pythonによるwebアプリケーション入門 - Django編-
PPTX
FINAL FANTASY Record Keeperを支えたGolang
PDF
GoでMinecraftっぽいの作る
PPTX
【初心者向け】Go言語勉強会資料
PDF
Go MobileでAndroidアプリ開発
PDF
PythonによるWebスクレイピング入門
No te comas la coma
Scalaと過ごした5ヶ月間
Hpcビジネスコンテンスト発表資料
Pythonについて
Pythonおじさんのweb2py挑戦記
ScalaでAndroidアプリ開発
Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話
Scala 初めての人が Heroku で Web アプリを公開するまで
多分モダンなWebアプリ開発
Pythonの開発環境を調べてみた
数理最適化とPython
めんどくさくない Scala #kwkni_scala
コンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashi
ヒカルのGo 資料 Webアプリケーションの作り方
Pythonによるwebアプリケーション入門 - Django編-
FINAL FANTASY Record Keeperを支えたGolang
GoでMinecraftっぽいの作る
【初心者向け】Go言語勉強会資料
Go MobileでAndroidアプリ開発
PythonによるWebスクレイピング入門
Ad

Similar to Wrapping a C++ library with Cython (20)

PDF
Cython intro prelerease
PDF
Cython ことはじめ
PDF
Pyconjp2014_implementations
PDF
次世代言語 Python による PyPy を使った次世代の処理系開発
ODP
Introduction of Python
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
PDF
PyPy 紹介
PDF
「Python言語」はじめの一歩 / First step of Python / 2016 Jan 12
PDF
Python Kyoto study
KEY
ひのきのぼうだけで全クリ目指す
PPT
Python languageupdate (2004)
PDF
Introduction to Numpy (and Python) [JPN]
KEY
Hello World Python featuring GAE
PDF
Pythonで始めるDropboxAPI
PDF
LLdeade Python Language Update
PDF
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
PPTX
Boost.python
PPTX
Boost.python
PDF
Pythonを取り巻く開発環境 #pyconjp
PDF
ctypes拡張モジュール
Cython intro prelerease
Cython ことはじめ
Pyconjp2014_implementations
次世代言語 Python による PyPy を使った次世代の処理系開発
Introduction of Python
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
PyPy 紹介
「Python言語」はじめの一歩 / First step of Python / 2016 Jan 12
Python Kyoto study
ひのきのぼうだけで全クリ目指す
Python languageupdate (2004)
Introduction to Numpy (and Python) [JPN]
Hello World Python featuring GAE
Pythonで始めるDropboxAPI
LLdeade Python Language Update
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
Boost.python
Boost.python
Pythonを取り巻く開発環境 #pyconjp
ctypes拡張モジュール

Wrapping a C++ library with Cython

  • 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. Outline 1. Introduction 2. Cython 3. Python/C API 4. Summary 3 / 39
  • 5. 動機 Python と C/C++の両方の長所を活かしたい C/C++ 実行速度の速さ データ構造, 数値計算ライブラリが揃っている → 計算量が支配的な箇所に使う Python 読み書きしやすさ, 柔軟性, 拡張性, ポータビリティ 利便性の高いライブラリが揃っている → その他のすべての箇所に使う データ収集, 前処理 コマンドライン, GUI アプリ, ウェブアプリ 設定ファイル, ジョブ管理, ログ管理 テスト, 可視化, ドキュメンテーション, · · · ⇒ Python から C/C++を呼び出せればよい 5 / 39
  • 7. Python/C API Python/C API を用いて Python の拡張モジュールを作成することに より以下が可能となる. 新しいオブジェクトの追加 C/C++の呼び出し http://docs.python.jp/2/c-api/index.html http://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.py setup(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, *g cdef struct Rectangle: float width float height cdef enum State: open = 1 closed = 2 cdef object pyobj ctypedef unsigned long uint64_t from libc.stdint cimport int64_t 15 / 39
  • 16. 型変換 基本的な数値型と文字列型については, Python オブジェクトと C 変数が自動変換される. cdef bytes py_byte_string cdef unicode py_unicode_string cdef char* c_string py_byte_string = <bytes> c_string py_byte_string = c_string py_byte_string = c_string[:length] c_string = py_byte_string py_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 * dx cdef 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.x0 def 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_PI def 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 string cdef string cpp_string cdef bytes py_byte_string cpp_string = <string> py_byte_string cpp_string = py_byte_string py_byte_string = cpp_string 23 / 39
  • 24. C++クラスの宣言 pair.pyx cdef 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.py setup(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
  • 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