PythonからC言語(my.puts)を呼び出して実行する
- 作成日: 2021-07-26
- 更新日: 2023-12-24
- カテゴリ: Python
PythonからC言語(my.puts)を呼び出して実行する
PythonはC言語で書かれたモジュールを呼び出すことが出来ます。
この記事ではその方法を解説します。
簡単に言うと、まずC言語でモジュールを書きます。
このモジュールはPythoの規約に沿った書き方をする必要があります。
それからそのモジュールをgcc
などのコンパイラでコンパイルして共有ライブラリにします。
コンパイルした共有ライブラリをPythonインタプリタからインポートして、定義したモジュールのメソッドを呼び出します。
これが一連の流れです。
C言語でモジュールを書く
C言語でモジュールを書くわけですが、今回は「my
」モジュールと言うモジュールを作ります。
そして「puts
」という関数をmy
モジュールの中に定義します。
コードにすると↓のようになります。
/**
* my モジュール
*
* インポートすると puts 関数を使える
*
* コンパイル例:
* gcc -I /usr/include/python3.5m -fPIC -Wall -shared -o my.so my.c
*/
// コンパイラのフラグ -I に Python.h のあるディレクトリを指定する必要がある
#include <Python.h>
/**
* my モジュールのメソッド
* 引数の文字列を標準出力に出力してその長さを返す
*/
PyObject* my_puts(PyObject* self, PyObject* args)
{
const char* name;
// args をパースして name に値を保存する
// "s" は文字列を表す
// args を "s" でパースしろという命令
if (!PyArg_ParseTuple(args, "s", &name))
return NULL;
long len = strlen(name); // 文字列の長さを取得
int result = puts(name); // name を stdout に出力
if (result == EOF) { // 結果が失敗だったら
len = result; // len に EOF(-1) を入れる
}
// 文字列の長さを返す
// PyLong_FromLong は整数オブジェクトを生成する
return PyLong_FromLong(len);
}
// モジュール内のメソッドを定義する
// puts がメソッド名で my_puts がメソッドの本体
// METH_VARARGS は引数の定義
// 一番最後にメソッドの説明
static PyMethodDef my_methods[] = {
{"puts", my_puts, METH_VARARGS, "Print argument string to stdout"},
{NULL}, // 番兵
};
// モジュールのドキュメント
#define my_doc \
"My module is my module.\n"
// モジュールの定義
static struct PyModuleDef module =
{
PyModuleDef_HEAD_INIT,
"my", // モジュール名。インポートするときに使用される名前
my_doc, // モジュールのドキュメント
-1, // モジュールのインタプリタのステートのサイズ
my_methods // モジュール
};
// モジュールの初期化
// PyInit_(モジュール名)になる
// 今回は my モジュールを作るので PyInit_my になる
PyMODINIT_FUNC PyInit_my(void)
{
return PyModule_Create(&module);
}
モジュールをコンパイルする
先ほどのモジュール(my.c
)をコンパイルするには↓のようにします。
$ gcc -I /usr/include/python3.5m -fPIC -Wall -shared -o my.so my.c
↑のように-shared
フラグを付けて共有ライブラリ(my.so
)としてコンパイルします。
-I
フラグのパスは環境によって変わります。
筆者の環境では/usr/include/python3.5m
ディレクトリ以下にPython.h
があったので、ここを指定しています。
モジュールをインポートする
Pythonインタプリタを起動してモジュールをインポートし、puts()
関数を実行します。
$ ls
my.c my.so
$ python
import my
result = my.puts("Hi")
# Hi
print(result)
# 2
以上のようにC言語で書かれたモジュールをPythonから呼び出すことが出来ました。
おわりに
Pythonではこのように簡単にC言語と連携を取ることが出来ます。
速度の必要な処理を書きたい場合はC言語を使えばいいわけですね。
🦝 < 便利だな~
🐭 < Python様様