C/C++ で Python 拡張を作る
準備
事前に、
- apt install python3-dev
- yum install python39-devel
等を実行し、Python の開発モジュールをインストールしてから実行してください。
C/C++ で Python 拡張を作成する場合
とりあえず、C++で myModule
作成する。
-
必要なファイル
-
setup.py
setup.pyfrom distutils.core import setup, Extension setup(name = 'myModule', version = '1.0.0', \ ext_modules = [Extension('myModule', ['extention.cpp'])])
-
extention.cpp
extention.cpp/*** ヘッダのインクルードパスにバージョンが入るので注意が必要です ***/ #include <python3.7m/Python.h> static PyObject* c_helloworld(PyObject* self, PyObject* args) { printf("Hello Work ... Cpp\n"); return Py_None; } /******************************************************************************/ /* ここから下はPython拡張の定型的な記述になります。 */ // myModule definition(python's name) static PyMethodDef myMethods[] = { { "hellowork", c_helloworld, METH_NOARGS, "Prints Hello Work" }, { NULL } }; // myModule definition struct static struct PyModuleDef myModule = { PyModuleDef_HEAD_INIT, "myModule", "Python3 C/C++ API Module Sample", -1, myMethods }; // Initializes myModule PyMODINIT_FUNC PyInit_myModule(void) { return PyModule_Create(&myModule); }
-
-
ビルド&インストール
$ python3 setup.py build $ sudo python3 setup.py install
build
は省略しても問題ないです。 -
実行例
>>> import myModule as m >>> m.hellowork() Hello Work ... Cpp
Python から引数をもらって戻り値を返す
特に意味はないですが、$a + b = c$ を行う Python拡張を、上記の extention.cpp に追加します。
-
追加関数
extention.cppstatic PyObject* pyadd(PyObject* self, PyObject* args) { int a, b, c; // 関数引数が (int, int) なので "ii" を指定しています if (! PyArg_ParseTuple(args, "ii", &a, &b)){ return NULL; } c = a + b; // 戻り値が int なので "i" を指定しています return Py_BuildValue("i", c); }
-
メソッド登録
extention.cpp// myModule definition(python's name) static PyMethodDef myMethods[] = { { "hellowork", c_helloworld, METH_NOARGS, "Prints Hello Work" }, { "add", pyadd, METH_VARARGS, "a + b = c"}, /* この行を追加 */ { NULL } };
-
実行例
>>> import myModule as m >>> ret = m.add(33, 66) >>> ret 99
戻り値としてリストを返す
-
関数追加
extention.cppstatic PyObject* returnList(PyObject* self, PyObject* args) { return Py_BuildValue( "[[s,s,s,s],[i,i,i,i]]", "label1", "label2", "label3", "label4", 1,2,3,4 ); }
-
関数の登録
extention.cpp// myModule definition(python's name) static PyMethodDef myMethods[] = { { "hellowork", c_helloworld, METH_NOARGS, "Prints Hello Work" }, { "add", pyadd, METH_VARARGS, "a + b = c"}, { "returnList", returnList, METH_NOARGS, "return List Sample" }, /* この行追加 */ { NULL } };
-
実行例
>>> import myModule as m >>> ret = m.returnList() >>> ret[0] ['label1', 'label2', 'label3', 'label4'] >>> ret[1] [1, 2, 3, 4]
参考サイト
Cython: C-Extensions for Python で Python 拡張を作る
基本形
事前に sudo pip3 install cython
などを実行し、Cython をインストールしておいてください。
Cython を利用すると、Python の方が便利な処理は Python でコードを書き、C/C++ じゃないとダメなところだけ、C/C++ にすることができます。
Python はループ処理が遅い傾向があるため、大量のループを必要とする処理を C/C++ で実装することで高速化する、というような使い方をするらしい。
-
必要なファイル
-
extention.pyx
extention.pyximport cython # pythonから呼び出す関数 def hellowork(): print("Hello Work ... cython") return None
-
setup.py
setup.pyfrom distutils.core import setup, Extension from Cython.Build import cythonize ext = Extension("myModule2", sources=["extention.pyx"], include_dirs=['.']) setup(name="myModule2", ext_modules=cythonize([ext]))
-
ビルド&インストール方法、実行例は C/C++ と同様なので省略。
足し算の結果を返す
-
extention.pyx に追加する関数
extention.pyxdef add(int a, int b): cdef: int c; c = a + b return c
Cython で C 実装関数を実行する
-
extention.pyx に追加する import文、関数
extention.pyxfrom cextention cimport c_hellowork_msg # ・・ # def cpp_hellowork(): cpp_hellowork_msg() return None
-
cextention.pxd (新規追加)
cextention.pxdcdef extern from "cextention.h": void c_hellowork_msg()
-
cextention.c (新規追加)
cextention.c#include <stdio.h> void c_hellowork_msg() { printf("Hello Work ... c\n"); }
-
cextention.h (新規追加)
cextention.h#ifndef _CEXTENTION_H_ #define _CEXTENTION_H_ void c_hellowork_msg(); #endif
-
setup.py (ビルド対象ファイル追加)
sources
に"cextention.c"
を追加します。setup.pyfrom distutils.core import setup, Extension from Cython.Build import cythonize ext = Extension("myModule2", sources=["extention.pyx", "cextention.c"], include_dirs=['.']) setup(name="myModule2", ext_modules=cythonize([ext]))
その他
Cython で C++ 実装関数を実行する場合、C と同じ方法ではダメなようです。
いまいち、理解できていないので、その内、勉強し直して更新しようと思います。