というわけで1日目の最後のエントリー。1日目は濃い目のトークが多かったせいか終わった後の疲労感がハンパなかったっす。
実践C拡張モジュール開発
- @mopemopeさん
- Abby CTO
- スライド
C拡張モジュールを書く意義について
- Pythonでないといけないのか?
- Java, Go, Lispなど
- Rustはやめておけ
- Cのライブラリを呼ぶだけならctypesでおk
- 今ならばPyPyも検討
- 必要な箇所だけCで書く高速化
- パフォーマンス
- Cコンパイラによる最適化の恩恵
なぜCythonではダメなのか?
- 学習コスト
- 構文などCython自身の知識が必要
- C/APIの知識も必要
- Cデバッガで追うことになった場合の対応が難しい
開発環境の準備
- C/API ドキュメント
- コンパイラ
- 開発用Python(debugビルド)
- ビルドに必要なライブラリ
- virtualenv, py.test or nose
- デバッガ(gdb)
- Valgrind
./configure --prefix=~/opt/py33 --with-pydebug --with-valgrind make make install
DebugモードのPythonについて
- メモリプールの無効化
- 無効にしないとリーク検出が難しい
- 生存Object数の表示
- closeされていないFDなど各種warning表示
- Valgrind
その他準備
- エディタ
- coredumpを吐くようにしておく
$ ulimit -c unlimited
setuptools, distribute
$ python setup.py develop
開発ディレクトリがライブラリのパスに入る
実際の開発
C, Pythonで別々にしておく
- src
- Cソース・ヘッダー
- jega - pythonパッケージ
ディレクトリはC/Pythonで分けた方が無難
setup.pyの役割
- distutilsを使ってモジュールをビルドするためのもの。Makefileはいらない
- 環境の判別
- コンパイルするソース指定
- コンパイルオプションの設定
- ライブラリのヘッダー、リンク
- configure なども実行できる
- C拡張以外のPythonパッケージのインストール
まずutil関数を書いておく
- OS,Pythonのバージョンアップチェック
- Cファイルの一覧作成
- デバッグモードなどマクロの切り替え
- 他のライブラリのヘッダーファイルの検索
Python C/API
- 略語が少ないため、コードが読みやすい
- ユーティリティ関数も準備されている
- 2.x, 3.xでもほぼ変わらない(安定)
- ドキュメントもしっかりしている
コードの記述
ソースファイル
* 1機能毎にわける
* シンプルなファイル名
* ヘッダーとソースは用意する
- 構造体
- PyObjectの場合は大文字から始める
- それ以外は_tで終わる
- 接頭語
- モジュール:ExampleMod_xxxx
- クラス名_メソッド名
static PyMethodDef LoopObject_methods[] = { { "switch", ... } }
Cであるので必ず返り値を返し、エラーであるかをチェックする
- 例外が発生している場合には必ずNULLを返す
- Noneを帰す場合は、 Py_RETURN_NONE を返す
その他の場合:intでエラー時には負の数を返す
New reference
- 参照が +1 されて返る
- 通常のPythonコードもコレにあたる
Borrowed Reference
- 参照カウントが上がらない
- Tuple などがこれにあたる
参照カウントの規則
- PyObject *型を返す関数
- 必ず Py_INCREF をしてから返す
- 呼び出し側で Py_DECREF するコードで統一
- Borrowedは別関数として分ける
- DECREF していいのかをわかりやすく
- 内部で使いまわしたい
ThreadとGIL
Pythonから呼ばれる以上、スレッドセーフになっている場合がほとんど。N/W IOが走る場合は下記で囲んでおく
- Py_BEGIN_ALLOW_THREADS
- Py_END_ALLOW_THREADS
インスタンス継承
- Cで作成したクラスをPython側で継承
その他
- Cでも iter を使おう
- PyObject_GetIter でiterを取得
- PyIter_Nextで繰り返す
- PySequence_Fast
- 高速
DEBUGマクロを使おう
- 関数の最初、最後にかならずログを表示
- オブジェクトの生成・削除のログは必ず取る
マクロによる分岐
PyBytesString使う
質疑応答
- まずはPythonで書いてみて、本当に遅いか判断する
- Pythonで書くのが大変だと、Cだとさらに大変になる
0 件のコメント:
コメントを投稿