スポンサーリンク

Windows + VC++ + Python/C APIでPythonからCを呼び出す(4)Cへ複数の引数を渡す

Python/C APIでは引数を複数渡す場合、第二引数にPython側から渡された引数がすべてまとめられている。それを取り出すためにPyArg_ParseTupleを使うのだが、この時何番目の引数の型が何かを関数へ教えてやる必要がある。

下の例では、それが第二引数の"ii"となっている。

簡単な例

mymod.hpp

// 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

// 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); }

test.py

import DLLforPython

print( DLLforPython.add(2,3) )

PyArg_ParseTuple の第二引数について

データ型によってどのような指定を行うかは以下に書かれている。

https://docs.python.org/ja/3/c-api/arg.html

mymod.hpp 変更

// 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

// 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;
}

test.py

import DLLforPython

DLLforPython.function(
    True,
    "hello",
    5,
    4.8,
    3+2j
)
bool true
char hello
long 5
float 4.800000
complex 3.000000+i2.000000

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: