Cのアルゴリズム本で漸化式のサンプルがあったのをPythonのC拡張に試しに落とし込んでみた。
<some_dir>/ | -- build.sh | -- ext.c `-- tests.py
ext.c
longのオーバーフロー処理はしてないです。悪しからず。
#include <Python.h> long combi(int, int); static PyObject * recurrence_formula(PyObject *self, PyObject *args){ int arg; int n, r; PyListObject *list; if(!PyArg_ParseTuple(args, "i", &arg)){ return NULL; } list = (PyListObject *) PyList_New(arg); for(n=0; n<arg; n++){ for(r=0; r<=n; r++){ PyList_SET_ITEM(list, r, Py_BuildValue("l", combi(n, r))); } } return Py_BuildValue("O", list); } long combi(int n, int r){ int i; long p=1; for(i=1; i<=r; i++){ p = p * (n - i + 1) / i; } return p; } // ext.__doc__ static char ext_doc[] = "C extention module documentation."; // ext.recurrence_formula.__doc__ static char recurrence_formula_docs[] = "list recurrence_formula(int): return result number that recurrence formula ."; // ext.<function name>.__doc__ static PyMethodDef methods[] = { {"recurrence_formula", recurrence_formula, METH_VARARGS, recurrence_formula_docs}, {NULL, NULL} }; void initext(void) { Py_InitModule3("ext", methods, ext_doc); }
tests.py
簡単なテスト書いとくと楽だった。
import unittest try: import ext except ImportError, e: raise e class TestSequenceFunctions(unittest.TestCase): def setUp(self): pass def test_recurrence_formula(self): array = ext.recurrence_formula(1) self.assertEqual(array, [1]) array = ext.recurrence_formula(10) self.assertEqual(array, [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]) try: array = ext.recurrence_formula("argument is string.") except TypeError: self.assert_("argument is stirng.") if __name__ == '__main__': unittest.main()
build.sh
コンパイルとテストを自動化しとくと楽だった。
#!/bin/bash # old file delete. #rm -f ext.o #rm -f ext.so # compile. gcc -fPIC -c ext.c -I /usr/include/python2.6/ gcc -shared -O3 -o ext.so ext.o # test sweet. echo "Unit Test" python tests.py
まとめ。
- Cはhelloworld程度しか書いたことなかたけど、動くとこまではできた。
- これがベストプラクティスかは別。
- 意外と簡単に作れた。ドキュメントそろってるから楽。