Python から C の呼出し – 2
先日 Python から C を呼び出す関係を調べていて Synology NAS に Python.h がなかった.
検索 をかけると DSM「パッケージ センター」-「Python3」では python-dev が入ってないらしい.
次の様な手順で python-dev をインストール.
# sudo -i
# cd /var/services/homes/Iwao/
# source ./set_ds_inc.sh
# opkg install python-dev
# opkg install python3-dev
コンパイルで必要なファイルは次の所に入った.
/volume1/@entware-ng/opt/include/python3.6/Python.h
/volume1/@entware-ng/opt/include/python2.7/Python.h
Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$ g++ g3d_to.cpp -Wall -fPIC -o g3d_to.so -shared g3d_to.cpp:9:20: fatal error: Python.h: No such file or directory ^ compilation terminated. Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$ g++ g3d_to.cpp -Wall -fPIC -o g3d_to.so -shared -I /volume1/@entware-ng/opt/include/python3.6/ Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$ ll total 9568 drwxrwxrwx+ 3 Iwao users 4096 Aug 5 10:29 . drwxrwxrwx+ 3 Iwao users 4096 Aug 5 09:50 .. -rwxrwxrwx+ 1 Iwao users 3941375 May 7 18:03 3887.imo -rwxrwxrwx+ 1 Iwao users 1241865 Jul 7 15:13 7801.imo drwxrwxrwx+ 2 Iwao users 4096 Aug 5 10:29 bak -rwxrwxrwx+ 1 Iwao users 1688 Aug 4 15:04 g3d_to.cpp -rwxrwxrwx 1 Iwao users 2654136 Aug 5 10:29 g3d_to.so -rwxrwxrwx+ 1 Iwao users 1644 Aug 7 2019 gons_to.cpp -rwxrwxrwx 1 Iwao users 1931244 Aug 5 10:17 gons_to.out Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$ python3 Python 3.6.2 (default, Jan 11 2018, 10:32:53) [GCC 6.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import g3d_to >>> dir(g3d_to) ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'gons_to', 'load', 'save'] >>> g3d_to.load("./7801.imo") >>> g3d_to.save("./7801.stl") >>> g3d_to.save("./7801.ac") >>> Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$ ll total 10252 drwxrwxrwx+ 3 Iwao users 4096 Aug 5 10:31 . drwxrwxrwx+ 3 Iwao users 4096 Aug 5 09:50 .. -rwxrwxrwx+ 1 Iwao users 3941375 May 7 18:03 3887.imo -rwxrwxrwx+ 1 Iwao users 438369 Aug 5 10:31 7801.ac -rwxrwxrwx+ 1 Iwao users 1241865 Jul 7 15:13 7801.imo -rwxrwxrwx+ 1 Iwao users 254784 Aug 5 10:31 7801.stl drwxrwxrwx+ 2 Iwao users 4096 Aug 5 10:29 bak -rwxrwxrwx+ 1 Iwao users 1688 Aug 4 15:04 g3d_to.cpp -rwxrwxrwx 1 Iwao users 2654136 Aug 5 10:29 g3d_to.so -rwxrwxrwx+ 1 Iwao users 1644 Aug 7 2019 gons_to.cpp -rwxrwxrwx 1 Iwao users 1931244 Aug 5 10:17 gons_to.out Iwao@DS116:~/pyt_test/call_c/call_cpp/g3d_to$
Python から CPP の呼出し – 2
予めデータ(vv_PLF)を作成して,必要に応じてファイルに出力するコード.
vv_PLF* get_vv_PLF (void) { static vv_PLF G_PLF ; return &G_PLF ; } static PyObject* check_rd (PyObject* self, PyObject* args) { vv_PLF* gvv_plf = get_vv_PLF() ; vv_PLF vv_plf_ = ::Check_Revise_deg() ; *gvv_plf = vv_plf_ ; return Py_None ; } static PyObject* dump_svg (PyObject* self, PyObject* args) { vv_PLF* gvv_plf = get_vv_PLF() ; ::Dump_SVG(*gvv_plf) ; return Py_None ; } static PyObject* dump_ipl (PyObject* self, PyObject* args) { vv_PLF* gvv_plf = get_vv_PLF() ; ::Dump_ipl(*gvv_plf) ; return Py_None ; }
Python 側では
* check_rd でデータを作成.
* dump_svg などでデータを出力.
3D データを読み込んで,指定されたファイル名(拡張子により形式を判断)で出力.
static PyObject* load (PyObject* self, PyObject* args) { const char* str_file = NULL ; if (!PyArg_ParseTuple(args,"s",&str_file)) { return NULL ; } tstring g3_file = str_file ; GonsA gnsa = ::To_GonsA(g3_file.c_str()) ; set_GonsA(gnsa) ; return Py_None; } static PyObject* save (PyObject* self, PyObject* args) { const char* str_file = NULL ; if (!PyArg_ParseTuple(args,"s",&str_file)) { return NULL ; } tstring g3_file = str_file ; GonsA* gnsa = ::get_GonsA() ; ::GonsA_To(*gnsa,g3_file.c_str()) ; return Py_None; } static PyObject* gons_to (PyObject* self, PyObject* args) { const char* str_file = NULL ; if (!PyArg_ParseTuple(args,"s",&str_file)) { return NULL ; } tstring g3_file = str_file ; gons_to(g3_file.c_str()) ; return Py_None; }
Python から CPP の呼出し
雰囲気はつかめてきたので,以前作成した cpp を呼んでみることに…
実際の処理部分は C++ のコードだが,呼び出しは C の関数.
また引数もない状態なので,C 関数の system(“a.out”) と呼んでいるのと同様.
#include "i_rd_dbg.hxx" int _tmain(int argc, TCHAR* argv[]) { ::Test_Revise_deg() ; return 0 ; }
#include <Python.h> #include "i_rd_dbg.hxx" #include "messbar.cxx" static PyObject* call_cpp(PyObject* self, PyObject* args) { ::Test_Revise_deg() ; return Py_None ; } static PyMethodDef myMethods[] = { { "_call_cpp_", call_cpp, METH_NOARGS, "call cpp" }, { NULL }, } ; static struct PyModuleDef call_mod = { PyModuleDef_HEAD_INIT, "call_mod", "call_cpp module", -1, myMethods } ; PyMODINIT_FUNC PyInit_call_mod(void) { return PyModule_Create(&call_mod) ; }
コンパイルして import まではできたが,メソッドをうまく呼び出せない.
>>> call_mod.call_cpp()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module ‘call_mod’ has no attribute ‘call_cpp’
>>>
それで,メソッドを表示できないかと思い検索すると,
python でメソッドの一覧を取得する方法
他に dir(call_mod) もあった.
Iwao@AS5202T:/volume1/home/Iwao/test/test_py/call_c/call_cpp/T_Rvs_sc $ g++ rvs_sc_w.cpp -o call_mod.so -fPIC -Wall -shared -I /volume1/.@plugins/AppCentral/python3/include/python3.7m/ Iwao@AS5202T:/volume1/home/Iwao/test/test_py/call_c/call_cpp/T_Rvs_sc $ Iwao@AS5202T:/volume1/home/Iwao/test/test_py/call_c/call_cpp/T_Rvs_sc $ python3 Python 3.7.0 (default, Aug 23 2018, 17:48:39) [GCC 4.6.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import call_mod >>> call_mod.call_cpp Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'call_mod' has no attribute 'call_cpp' >>> call_mod.call_cpp() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'call_mod' has no attribute 'call_cpp' >>> obj = call_mod >>> import inspect >>> for m in inspect.getmembers(obj): ... print(m) ... ('__doc__', 'call_cpp module') ('__file__', '/volume1/home/Iwao/test/test_py/call_c/call_cpp/T_Rvs_sc/call_mod.so') ('__loader__', <_frozen_importlib_external.ExtensionFileLoader object at 0x7f5a1a35ec50>) ('__name__', 'call_mod') ('__package__', '') ('__spec__', ModuleSpec(name='call_mod', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x7f5a1a35ec50>, origin='/volume1/home/Iwao/test/test_py/call_c/call_cpp/T_Rvs_sc/call_mod.so')) ('_call_cpp_', <built-in function _call_cpp_>) >>> call_mod._call_cpp_() >>>