ナンクル力学系

学んだ事を書き連ねていこう。

python の C 拡張から python の関数を呼ぶ方法の例

with one comment

まんま「1.6 C から Python 関数を呼び出す」にかかれている方法だけど.

C拡張, setup.py, テスト用コード↓

callbackmodule.c

 #include <Python.h>

static PyObject *my_callback = NULL;

static PyObject *
my_set_callback(PyObject *dummy, PyObject *args)
{
  PyObject *result = NULL;
  PyObject *temp;

  if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
    if (!PyCallable_Check(temp)) {
      PyErr_SetString(PyExc_TypeError, "parameter must be callable");
      return NULL;
    }
    Py_XINCREF(temp);         /* 新たなコールバックへの参照を追加 */
    Py_XDECREF(my_callback);  /* 以前のコールバックを捨てる */
    my_callback = temp;       /* 新たなコールバックを記憶 */
    /* "None" を返す際の定型句 */
    Py_INCREF(Py_None);
    result = Py_None;
  }
  return result;
}

static PyObject *
my_call_callback(PyObject *dummy, PyObject *args)
{
  PyObject *callback_arg;
  PyObject *result;

  if (! PyArg_ParseTuple(args, "O:call_callback", &callback_arg)) {
    return NULL; /* PyArg_ParseTuple has raised an exception */
  }

  /* ここでコールバックを呼ぶ */
  result = PyEval_CallObject(my_callback, callback_arg);
  if (result == NULL){
    return NULL; /* エラーを返す */
  }
  /* 場合によってはここで結果を使うかもね */
  /* Py_DECREF(result); //これやったら,segmentation fault で落ちた */
  return result;
}

static PyObject *
my_call_callback2(PyObject *dummy, PyObject *args)
{
  PyObject *callback_arg;

  if (! PyArg_ParseTuple(args, "O:call_callback", &callback_arg)) {
    return NULL; /* PyArg_ParseTuple has raised an exception */
  }
  return PyEval_CallObject(my_callback, callback_arg);
}

static PyMethodDef module_methods[] = {
  {"my_set_callback", (PyCFunction)my_set_callback, METH_VARARGS, "set callback"},
  {"my_call_callback",(PyCFunction)my_call_callback, METH_VARARGS, "call callback"},
  {"my_call_callback2",(PyCFunction)my_call_callback2, METH_VARARGS, "call callback"},
  {NULL}  /* Sentinel */
};

 #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
 #define PyMODINIT_FUNC void
 #endif
PyMODINIT_FUNC
initcallback(void)
{
  (void) Py_InitModule("callback", module_methods);
}

メモ

初めに作ったのが my_call_callback で,かなりコードが絞れることが分かったので my_call_callback2 も書いてみた.やることは同じ.

setup.py

from distutils.core import setup, Extension

module1 = Extension(
        'callback',
        sources = ['callbackmodule.c']
)

setup(
        name = 'my',
        ext_modules = [module1],
)

test.py

import callback

x = (1,2,3)
y = dict(a=2,c=2)

callback.my_set_callback(list)
print callback.my_call_callback((x,))
print callback.my_call_callback((y,))

callback.my_set_callback(type)
print callback.my_call_callback((x,))
print callback.my_call_callback((y,))

callback.my_set_callback(list)
print callback.my_call_callback2((x,))
print callback.my_call_callback2((y,))

callback.my_set_callback(type)
print callback.my_call_callback2((x,))
print callback.my_call_callback2((y,))

コンパイル (その場にcallback.soを作る)

python setup.py config build build_ext –inplace

テスト:

% python test.py
[1, 2, 3]
['a', 'c']
<type 'tuple'>
<type 'dict'>
[1, 2, 3]
['a', 'c']
<type 'tuple'>
<type 'dict'>

Written by tkf

May 11, 2009 at 8:28 pm

Posted in PC, programming

Tagged with ,

One Response

Subscribe to comments with RSS.

  1. I choose to introduce myself to you, I am Len though I don’t really like being called like through which.

    One of his favorite hobbies is hot air balooning but he is struggling to locate time because.
    Oregon is where her home is and she loves finished, get the living
    recently there. My day job is a people managers.
    I’ve been working in my small website several time . Check it out here: ペルゴレージ

    ペルゴレージ

    May 30, 2014 at 4:35 am


Leave a comment