将 Cython class 对象作为参数传递给 C 函数

Passing Cython class object as argument to C function

我正在尝试将 Cython 实例 class 对象作为参数传递给 C 函数 - 因此它可以对其方法进行回调。

这是我试过的:

sample.c
#include "python.h"

void c_func(PyObject *obj){
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();

    /* Dictionary Object - can be of any dynamic type */

    PyObject *dict_obj = PyDict_New();
    PyObject *key = PyUnicode_FromString("average-run");
    PyObject *val = PyLong_FromLong(45445);
    PyDict_SetItem(dict_obj, key, val);

    /* Make a callback */

    PyObject_CallMethod(obj, "func_a", "(d)", dict_obj);

    PyGILState_Release(gstate);
}
pysample.pxd
cdef extern from "sample.h":
    void c_func(object obj)

cdef class Test(object):
    cdef func_a(self, object dict_obj)
pysample.pyx
cimport pysample
from pysample cimport Test

cdef class Test(object):
    cdef func_a(self, object dict_obj):
        print(dict_obj)

    def run_test(self):
        # Here I make a call to the C function
        pysample.c_func(self)

很遗憾,C 的回调无效。你能发现我做错了什么或提出修复建议吗?

问题已解决。这是因为 class 中的方法被定义为 cdef 而不是 cpdef.

sample.c
#include "python.h"

void c_func(PyObject *obj){
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();

    /* Dictionary Object - can be of any dynamic type */

    PyObject *dict_obj = PyDict_New();
    PyObject *key = PyUnicode_FromString("average-run");
    PyObject *val = PyLong_FromLong(45445);
    PyDict_SetItem(dict_obj, key, val);

    /* Make a callback */

   PyObject *res = PyObject_CallMethod(obj, "func_a", "(O)", dict_obj);

   if( !res )
   {
       PyErr_Print();
   }else
   {
      Py_DECREF(res); 
   }
   /* 
    * Note: Do not remove reference counting
    * for callback argument - python will take
    * care of it when the callback python method
    * go out of scope. If you do - it will cause
    * inconsistent data behaviour at the callback 
    * method side.
    */

   PyGILState_Release(gstate);
}
pysample.pxd
cdef extern from "sample.h":
    void c_func(object obj)

cdef class Test(object):
    cpdef func_a(self, object dict_obj)
pysample.pyx
cimport pysample
from pysample cimport Test

cdef class Test(object):
    cpdef func_a(self, object dict_obj):
        print(dict_obj)

    def run_test(self):
        # Here I make a call to the C function
        pysample.c_func(self)