COLUMN
組み込みエンジニアの戸惑い PythonからC言語を呼び出してみる①(Python/C APIを使った場合)
組み込みソフトウェアエンジニアがPythonを始めてみました。そして、第5の戸惑い、今回は組み込みとは切っても切り離せない「C言語」に関しての話題です。
Pythonを扱っていて課題となり得る、処理速度の改善や過去資産の流用など、そんなときに役立つかもしれない、PythonからC言語を呼び出す方法についてのご紹介です。
PythonからC言語、またはC++を呼び出す方法には様々なものがあります。以前の記事でもPython/C API (Python.h)やSWIG、boost.pythonなどを使うことで実現可能とご紹介しましたが、実際の使い方や簡単な仕組みなどをお話していきます。
Python/C API (Python.h)
ご紹介するのはPythonからC言語を呼び出せる一番基本となるPython/C APIです。
Python/C APIはPythonインストール時に標準で含まれているC言語用のAPIを使用し拡張モジュールを作成することにより、Pythonからの呼び出しを実現しています。
― 他のC言語を呼び出す方法との違いは?
Python/C APIは、標準で含まれているAPIなので追加ライブラリなども必要なく、既存の資産などC/C++のコードにラッパーをかませれば、そのまま利用することが可能です。
しかし、PythonのバージョンによるAPIの互換性、ラッパーの複雑さなどがあだとなり、大量のC/C++を利用する場合には運用管理が一気に膨れ上がる可能性があります。そのため、他のC言語を呼び出す方法と比べると、Python/C APIはあまりメリットが少ないのも事実です。
― 仕組み
Python/C APIを使用して、ビルドから実行までの流れを確認しておきましょう。
流れはいたって単純で、元となるC/C++のファイル(.c/cpp)と、それに合わせて作成したラッパーファイル(.c/.cpp)をビルドします。ビルドして出来上がった共有ライブラリファイル(.so)をC/C++を呼び出したいPythonのコード上でインポートし、対象となる関数を呼ぶだけです。
C/C++ファイルの例
Pythonから呼び出したいC言語のファイルを作成します。
what.c
#include <stdio.h>
void doYouDo( const char* jobs ){
printf( “Hello, I am %s.\n”, jobs );
}
ラッパーファイルの例
PythonとC言語をつなぐラッパーファイルを作成します。
whatWrap.c (Python2.7向け)
#include “Python.h”
extern void doYouDo( const char* );
PyObject* doYouDo(PyObject* self, PyObject* args, PyObject* kw){
const char* jobs = NULL;
static char* argnames[] = {“jobs”, NULL};
if( !PyArg_ParseTupleAndKeywords( args, kw, “|s”, argnames, &jobs ) ){
return NULL;
}else{
doYouDo( jobs );
return Py_BuildValue( “” );
}
}
static PyMethodDef whatmethods[] = {
{ “doYouDo”, doYouDo, METH_VARARGS | METH_KEYWORDS, “” },
{ NULL, NULL, 0, NULL },
};
PyMODINIT_FUNC initwhat(){
Py_InitModule( “what”, whatmethods );
}
ビルドする
作成したC/C++ファイルとラッパーファイルをビルドします。
gcc -fPIC -Wall -c -o what.o what.c
gcc -fPIC -Wall -c -o whatWrap.o whatWrap.c
gcc -fPIC -Wall -shared -o whatModule.so what.o whatWrap.o
Pythonから呼び出す
準備は整ったので、最後にPythonから作成したC言語を呼び出してみましょう。
>>> import what
>>> what.doYouDo( ‘an embedded engineer’ )
Hello, I am an embedded engineer.
やはり、このような些細なコードでもラッパーファイルを作成するのが若干面倒くさく感じるので、Pythonから呼び出す関数が多くなればなるほど骨が折れそうです。ですが、C言語の呼び出す箇所が1か所だけといってシンプルな作業の場合には、ラッパーのフォーマットなどを用意しておけば割と簡単に使用できる機会があるかもしれません。
次回は引き続き、組み込みと言えばやっぱりC言語
「PythonでC言語を呼び出してみる②」の巻。
個別相談も承っております。下記よりお申し込みください。