Python/C APIでは引数を複数渡す場合、第二引数にPython側から渡された引数がすべてまとめられている。それを取り出すためにPyArg_ParseTupleを使うのだが、この時何番目の引数の型が何かを関数へ教えてやる必要がある。
下の例では、それが第二引数の"ii"となっている。
// mymod.hpp
#pragma once #include <Python.h> #pragma comment (lib,"python39.lib")
// C++側の関数宣言 // python側から引数が複数与えられる場合、 // 第二引数に全ての引数がまとめて入っている __declspec(dllexport) extern "C" PyObject * add_in_c(PyObject*, PyObject* xy);
// 関数へアクセスする方法一覧 static PyMethodDef method_list[] = { // Pythonで使用する関数名 , C++内で使用する関数名 , 引数の個数に関するフラグ , docstring { "add", (PyCFunction)add_in_c, METH_VARARGS , nullptr }, // 配列の最後は全てNULLの要素を入れておく { nullptr, nullptr, 0, nullptr } };
// モジュールを定義する構造体 static PyModuleDef module_def = { PyModuleDef_HEAD_INIT, "DLLforPython", // モジュール名 "Example of pyhton wrapper", // モジュール説明 0, method_list // Structure that defines the methods of the module }; PyMODINIT_FUNC PyInit_DLLforPython() { return PyModule_Create(&module_def); }
// mymod.cpp #include "mymod.hpp" PyObject* add_in_c(PyObject*, PyObject* xy) { long a, b;
// 引数xyからPython側から渡された二つの引数を取り出す // 第二引数の "ii" はaがint,bがintを表す int ret = PyArg_ParseTuple(xy, "ii", &a, &b); if (!ret) return NULL; return PyLong_FromLong(a + b); }
import DLLforPython print( DLLforPython.add(2,3) )
データ型によってどのような指定を行うかは以下に書かれている。
https://docs.python.org/ja/3/c-api/arg.html
// C++側の関数宣言 // python側から引数が複数与えられる場合、 // 第二引数に全ての引数がまとめて入っている __declspec(dllexport) extern "C" PyObject * function_in_c(PyObject*, PyObject* xy); // 関数へアクセスする方法一覧 static PyMethodDef method_list[] = { // Pythonで使用する関数名 , C++内で使用する関数名 , 引数の個数に関するフラグ , docstring { "function", (PyCFunction)function_in_c, METH_VARARGS , nullptr }, // 配列の最後は全てNULLの要素を入れておく { nullptr, nullptr, 0, nullptr } };
// mymod.cpp #include "mymod.hpp" PyObject* function_in_c(PyObject*, PyObject* args) { bool b; // PyArg_ParseTupleには b を与える char *s; // PyArg_ParseTupleには s を与える long i; // PyArg_ParseTupleには i を与える float f; // PyArg_ParseTupleには f を与える Py_complex d;// PyArg_ParseTupleには D を与える // 第三引数以降は可変長引数 int ret = PyArg_ParseTuple( args, "bsifD", &b, &s, &i, &f, &d ); printf("bool %s\n", b ? "true" : "false"); printf("char %s\n", s); printf("long %d\n", i); printf("float %lf\n", f); printf("complex %lf+i%lf\n", d.real, d.imag); return Py_None; }
import DLLforPython DLLforPython.function( True, "hello", 5, 4.8, 3+2j )