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

时间:2015-08-27 19:25:50

标签: python c cython cpython

我试图将Cython实例类对象作为参数传递给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的回调不起作用。你能发现我做错了什么或建议修复它吗?

1 个答案:

答案 0 :(得分:1)

问题已经解决。这是因为班级中的方法被定义为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)