これは予想以上に困難ですが、実行することができます。
あなたがコールバックとして提供したい単一のC関数を持っている場合は、呼び出し可能なPythonのに変換するPyCFunction_New
を使用することができます:あなたが選択したい場合は
#include <python.h>
static PyObject *my_callback(PyObject *ignore, PyObject *args)
{
/* ... */
}
static struct PyMethodDef callback_descr = {
"function_name",
(PyCFunction) my_callback,
METH_VARARGS, /* or METH_O, METH_NOARGS, etc. */
NULL
};
static PyObject *py_callback;
...
py_callback = PyCFunction_New(&callback_descr, NULL);
このアプローチは機能しません実行時に異なるコールバック、例えばCコールバック関数をPythonコールバックに変換する汎用のc_to_python
関数を提供します。その場合は、独自のtp_call
の拡張タイプを実装する必要があります。
typedef struct {
PyObject_HEAD
static PyObject (*callback)(PyObject *, PyObject *);
} CallbackObject;
static PyObject *
callback_call(CallbackObject *self, PyObject *args, PyObject *kwds)
{
return self->callback(args, kwds);
}
static PyTypeObject CallbackType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Callback", /*tp_name*/
sizeof(CallbackObject), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
(ternaryfunc) callback_call, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
};
PyObject *
c_to_python(PyObject (*callback)(PyObject *, PyObject *))
{
CallbackObject *pycallback = PyObject_New(CallbackObject, &CallbackType);
if (pycallback)
pycallback->callback = callback;
return pycallback;
}
このコードは自明もuser_data
ポインタを受け入れるように拡張されます。ユーザーデータをCallbackObject
構造体に格納するだけです。
http://stackoverflow.com/questions/6626167/build-a-pyobject-from-a-c-function(マージする必要があります、モッズポイント外)を参照してください。 – ecatmur
@ecatmurリンクされた回答が間違っています。 '' PyCFunction'は与えられた 'PyMethodDef'へのポインタを保持し、後でそれを使ってCの関数とフラグを検索するので、' methd'は静的に確保されなければなりません。答えのコードは 'PyMethodDef'を自動的に割り当てます。これは、結果のPython関数が呼び出されたときにクラッシュを引き起こします。 – user4815162342
@ user4815162342:リンクされた回答では、Manuxはプロセスの概要を示していたと思います。ちょっとばかげて、IMOというのは、Manuxは関数名を単に 'NULL'ではなくモジュール名として使うということです。実際のコードでは、 'PyMethodDef'がヒープに割り当てられていると仮定します。 – eryksun