rawtypes

python extension のコード生成に関するノート。

https://docs.python.org/3/extending/extending.html

  • python module(xxx.py を import すること)

  • python package(xxx/__init__.py を import すること)

  • python extension(ネイティブモジュールを指す。xxx.pyd)

PyCFunction

extension に登録する関数のシグネチャーは以下の通り。

static PyObject *EXPORT_FUNC(PyObject *self, PyObject *args);

すべて同じパターンでラップされる

  1. python の引数を ローカル変数(PyObject*)に展開する

  2. ローカル変数に展開した変数から、C の値を取り出してローカル変数に展開する。必要であれば、引数のデフォルト値をここで割り当てる。

  3. C の関数を呼び出す。

  4. 返り値が void の場合は、 None を返す。

  5. 返り値をローカル変数に入れる

  6. C の値から PyObject を作って返す。

// 例
static PyObject *imgui_Begin(PyObject *self, PyObject *args){
  // 1.
  // CStringType: const char *
  PyObject *t0 = NULL;
  // PointerType: bool*
  PyObject *t1 = NULL;
  // Int32Type: int
  PyObject *t2 = NULL;
  if(!PyArg_ParseTuple(args, "O|OO", &t0, &t1, &t2)) return NULL;
  // 2.
  const char *p0 = get_cstring(t0, nullptr);
  bool *p1 = t1 ? ctypes_get_pointer<bool*>(t1) :  NULL;
  int p2 = t2 ? PyLong_AsLong(t2) :  0;
  // 3. 5.
  auto value = ImGui::Begin(p0, p1, p2);
  // 6.
  PyObject* py_value = (value ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False));
  return py_value;
}