C/C++言語で作ってあるモジュール
double someFunc(double x);
があるとしよう。
これをPythonインタプリタ上で使う簡便なやり方をこの記事では示そうと思う。
###なぜPythonのインタプリタ上で動作させることにするのか?
・試行錯誤するのはpythonの方がやりやすい。
・Python上の枠組みでは、既存のC/C++の実装への影響を与えずに試行錯誤ができる。
・試行錯誤をすることで、適切な動作が何であるのかを見極めることができる。
###しかもSpyder統合環境のIPythonのコンソールを使おうとするのはなぜか?
・電卓が既に用意されている。
・ヒストリー機能が既に用意されている。
In [1]: a=1+2
In [2]: b= a +2
In [3]: history
a=1+2
b= a +2
history
In [4]:
・しかも標準のライブラリの中にヒストリーをファイルに保存する機能がある。
readline.write_history_file("history.py")
これを利用して
出来上がったhistory.py ファイルを実行させれば
一度、実行した結果を再現することが容易になる。
上記の
double someFunc(double x);
に対してwrapperを作ってあれば、
ここではwrapperもsomeFunc(x)という名前であるとすれば、
> y1 = someFunc(100.0)
> y2 = someFunc(100.0+10.0)
などのように実行することが可能になる。
> help(someFunc)
とすることで、
pythonのwrapper部分のhelpを表示できる。
実現しようとしている機能が本質的に対話的な作業である場合には
C/C++言語で上位層を作り上げるのではなく
IPythonのインタプリタで上位層を代用することによって
開発すべき範囲を大幅に減らすことができるだろう。
作成すべき機能の詳細を試行錯誤しながら作るときには、試行錯誤がどれだけ楽にできるかが
開発の速度に効いてくる。
楽にC/C++言語の自作ライブラリをPythonから利用可能にするには
C/C++言語のその機能を単一のプログラムとしてsomeFunc.exe
のように作成してみよう。
そのコマンドへの入出力の仕方を決めて
os.system("someFunc.exe 引数 > 結果ファイル")
のように実行できるようにする。
そして関数の戻り値は、結果ファイルに書き込まれるようにしておく。
その結果をファイルから読み込むように作るのが
いちばん楽に書き始められる書き方だろう[注1]。
そして、その自作コマンドを利用するpython関数を書き上げよう。
def someFunc(x):
ここにその自作コマンドを実行し
戻り値をr に代入するコードを書こう.
return r
そのような書き方でも、目的の作業を達成できるはずだ。
### その他の利点
- その関数への入力を自動化しやすい。
- for p in glob.glob("*.png"):とか for root, dirs, files in os.walk('.'):などを使って複数のファイルへの処理がしやすい。
- その関数の出力を加工しやすい。
- 結果をmatplotlibを使ってグラフにするのが簡単になる。
- C++で実装した機能よりも高次の階層で生じた部分(pythonで実装した部分)で生じたエラーは、python自体によってcall tree が表示されるので、どこでエラーを生じたのかがとても分かりやすい。
- 辞書やリストなどのデータ構造を簡単に使えるので、C++でのSTL(map, vector)相当の部分をもっと楽に使うことができる。
- 複雑なデータ構造をpickle ライブラリを使うことで簡単に保存、簡単に読み取ることができるので、データの保存・読み取りのために自作のライブラリを作る必要がほとんどなくなる。
- Spyder統合環境では、メモリにあるデータを、簡便に見ることができる。
IPythonインタプリタ上で、処理をさせているときにエラーを発生したとき、IPythonインタプリタ上には、その時点でのメモリが保存されています。変数をそのまま参照したり、別の処理を再開したりするのが容易です。コンパイラ言語で、プログラムを作成したときには、たいがいの場合、エラーを生じたときには、プログラムを異常終了してしまって再開の方法がありません。使い勝手のよい環境を実現するには、Pythonのインタプリタをその土台に使うのはとても楽な方法です。
注1:
os.system()
を使うよりはos.popen(), subprocess を使うのがいいでしょうし、
C や C++ による Python の拡張
を使う方がもっとよいでしょう。