SlideShare a Scribd company logo
1 of 39
Download to read offline
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

What's hot

中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
充足可能性問題のいろいろ
充足可能性問題のいろいろ充足可能性問題のいろいろ
充足可能性問題のいろいろHiroshi Yamashita
 
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデルMasashi Komori
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template MetaprogrammingAkira Takahashi
 
RによるBox-Cox変換
RによるBox-Cox変換RによるBox-Cox変換
RによるBox-Cox変換wada, kazumi
 
はじめてのKrylov部分空間法
はじめてのKrylov部分空間法はじめてのKrylov部分空間法
はじめてのKrylov部分空間法tmaehara
 
凡人の凡人による凡人のためのデザインパターン第一幕 Public
凡人の凡人による凡人のためのデザインパターン第一幕 Public凡人の凡人による凡人のためのデザインパターン第一幕 Public
凡人の凡人による凡人のためのデザインパターン第一幕 Publicbonjin6770 Kurosawa
 
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理Ken'ichi Matsui
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.kiki utagawa
 
Boost.Graph入門
Boost.Graph入門Boost.Graph入門
Boost.Graph入門egtra
 
ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)医療IT数学同好会 T/T
 
2 6.ゼロ切断・過剰モデル
2 6.ゼロ切断・過剰モデル2 6.ゼロ切断・過剰モデル
2 6.ゼロ切断・過剰モデルlogics-of-blue
 
ベイズ最適化
ベイズ最適化ベイズ最適化
ベイズ最適化MatsuiRyo
 
Hyperoptとその周辺について
Hyperoptとその周辺についてHyperoptとその周辺について
Hyperoptとその周辺についてKeisuke Hosaka
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロdigitalghost
 
異常検知と変化検知 9章 部分空間法による変化点検知
異常検知と変化検知 9章 部分空間法による変化点検知異常検知と変化検知 9章 部分空間法による変化点検知
異常検知と変化検知 9章 部分空間法による変化点検知hagino 3000
 
フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料Amelieff
 
PyMCがあれば,ベイズ推定でもう泣いたりなんかしない
PyMCがあれば,ベイズ推定でもう泣いたりなんかしないPyMCがあれば,ベイズ推定でもう泣いたりなんかしない
PyMCがあれば,ベイズ推定でもう泣いたりなんかしないToshihiro Kamishima
 
Rで階層ベイズモデル
Rで階層ベイズモデルRで階層ベイズモデル
Rで階層ベイズモデルYohei Sato
 

What's hot (20)

中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
PandasとSQLとの比較
PandasとSQLとの比較PandasとSQLとの比較
PandasとSQLとの比較
 
充足可能性問題のいろいろ
充足可能性問題のいろいろ充足可能性問題のいろいろ
充足可能性問題のいろいろ
 
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル
【読書会資料】『StanとRでベイズ統計モデリング』Chapter12:時間や空間を扱うモデル
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template Metaprogramming
 
RによるBox-Cox変換
RによるBox-Cox変換RによるBox-Cox変換
RによるBox-Cox変換
 
はじめてのKrylov部分空間法
はじめてのKrylov部分空間法はじめてのKrylov部分空間法
はじめてのKrylov部分空間法
 
凡人の凡人による凡人のためのデザインパターン第一幕 Public
凡人の凡人による凡人のためのデザインパターン第一幕 Public凡人の凡人による凡人のためのデザインパターン第一幕 Public
凡人の凡人による凡人のためのデザインパターン第一幕 Public
 
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理
基礎からのベイズ統計学 輪読会資料 第1章 確率に関するベイズの定理
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
 
Boost.Graph入門
Boost.Graph入門Boost.Graph入門
Boost.Graph入門
 
ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)
 
2 6.ゼロ切断・過剰モデル
2 6.ゼロ切断・過剰モデル2 6.ゼロ切断・過剰モデル
2 6.ゼロ切断・過剰モデル
 
ベイズ最適化
ベイズ最適化ベイズ最適化
ベイズ最適化
 
Hyperoptとその周辺について
Hyperoptとその周辺についてHyperoptとその周辺について
Hyperoptとその周辺について
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 
異常検知と変化検知 9章 部分空間法による変化点検知
異常検知と変化検知 9章 部分空間法による変化点検知異常検知と変化検知 9章 部分空間法による変化点検知
異常検知と変化検知 9章 部分空間法による変化点検知
 
フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料
 
PyMCがあれば,ベイズ推定でもう泣いたりなんかしない
PyMCがあれば,ベイズ推定でもう泣いたりなんかしないPyMCがあれば,ベイズ推定でもう泣いたりなんかしない
PyMCがあれば,ベイズ推定でもう泣いたりなんかしない
 
Rで階層ベイズモデル
Rで階層ベイズモデルRで階層ベイズモデル
Rで階層ベイズモデル
 

Viewers also liked

No te comas la coma
No te comas la comaNo te comas la coma
No te comas la comaPablo Rico
 
Scalaと過ごした5ヶ月間
Scalaと過ごした5ヶ月間Scalaと過ごした5ヶ月間
Scalaと過ごした5ヶ月間Haruki Okada
 
Hpcビジネスコンテンスト発表資料
Hpcビジネスコンテンスト発表資料Hpcビジネスコンテンスト発表資料
Hpcビジネスコンテンスト発表資料Hironori Nakajo
 
Pythonおじさんのweb2py挑戦記
Pythonおじさんのweb2py挑戦記Pythonおじさんのweb2py挑戦記
Pythonおじさんのweb2py挑戦記Yoshiyuki Nakamura
 
ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発ScalaでAndroidアプリ開発
ScalaでAndroidアプリ開発papamitra
 
Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話
Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話
Scala初心者がPlay/ScalaでロックなWebアプリを作ったお話omi end
 
Scala 初めての人が Heroku で Web アプリを公開するまで
Scala 初めての人が Heroku で Web アプリを公開するまでScala 初めての人が Heroku で Web アプリを公開するまで
Scala 初めての人が Heroku で Web アプリを公開するまでHideaki Miyake
 
多分モダンなWebアプリ開発
多分モダンなWebアプリ開発多分モダンなWebアプリ開発
多分モダンなWebアプリ開発tak-nakamura
 
Pythonの開発環境を調べてみた
Pythonの開発環境を調べてみたPythonの開発環境を調べてみた
Pythonの開発環境を調べてみたKenji NAKAGAKI
 
数理最適化とPython
数理最適化とPython数理最適化とPython
数理最適化とPythonYosuke Onoue
 
めんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scalaめんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scalaKazuhiro Sera
 
コンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashi
コンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashiコンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashi
コンピュータビジョンの最新ソフトウェア開発環境 SSII2015 チュートリアル hayashiMasaki Hayashi
 
ヒカルのGo 資料 Webアプリケーションの作り方
ヒカルのGo 資料 Webアプリケーションの作り方ヒカルのGo 資料 Webアプリケーションの作り方
ヒカルのGo 資料 Webアプリケーションの作り方Yosuke Furukawa
 
Pythonによるwebアプリケーション入門 - Django編-
Pythonによるwebアプリケーション入門 - Django編- Pythonによるwebアプリケーション入門 - Django編-
Pythonによるwebアプリケーション入門 - Django編- Hironori Sekine
 
FINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolangFINAL FANTASY Record Keeperを支えたGolang
FINAL FANTASY Record Keeperを支えたGolangYoshiki Shibukawa
 
【初心者向け】Go言語勉強会資料
 【初心者向け】Go言語勉強会資料 【初心者向け】Go言語勉強会資料
【初心者向け】Go言語勉強会資料Yuji Otani
 
Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Takuya Ueda
 
PythonによるWebスクレイピング入門
PythonによるWebスクレイピング入門PythonによるWebスクレイピング入門
PythonによるWebスクレイピング入門Hironori Sekine
 

Viewers also liked (20)

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

Similar to Wrapping a C++ library with Cython

Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cythonAtsuo Ishimoto
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門Shiqiao Du
 
Cython intro prelerease
Cython intro prelereaseCython intro prelerease
Cython intro prelereaseShiqiao Du
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23Masashi Shibata
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門伸男 伊藤
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presenKouhei Maeda
 
研究生のためのC++ no.2
研究生のためのC++ no.2研究生のためのC++ no.2
研究生のためのC++ no.2Tomohiro Namba
 
Boost.python
Boost.pythonBoost.python
Boost.pythonfate_fox
 
Boost.python
Boost.pythonBoost.python
Boost.pythonfate_fox
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0sunaemon
 
Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Jun MITANI
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいdigitalghost
 
C++プログラマの為のセキュリティ入門
C++プログラマの為のセキュリティ入門C++プログラマの為のセキュリティ入門
C++プログラマの為のセキュリティ入門道化師 堂華
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 

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

Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cython
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門
 
Cython intro prelerease
Cython intro prelereaseCython intro prelerease
Cython intro prelerease
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
C#勉強会
C#勉強会C#勉強会
C#勉強会
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presen
 
研究生のためのC++ no.2
研究生のためのC++ no.2研究生のためのC++ no.2
研究生のためのC++ no.2
 
Boost.python
Boost.pythonBoost.python
Boost.python
 
Boost.python
Boost.pythonBoost.python
Boost.python
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0
 
Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)Python 学習教材 (~299ページ)
Python 学習教材 (~299ページ)
 
C++0x総復習
C++0x総復習C++0x総復習
C++0x総復習
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
osakapy 2014.05 LT
osakapy 2014.05 LTosakapy 2014.05 LT
osakapy 2014.05 LT
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
C++プログラマの為のセキュリティ入門
C++プログラマの為のセキュリティ入門C++プログラマの為のセキュリティ入門
C++プログラマの為のセキュリティ入門
 
C++14 Overview
C++14 OverviewC++14 Overview
C++14 Overview
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 

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