C语言调用语言调用Python代码的方法代码的方法
问题问题
你想在C中安全的执行某个Python调用并返回结果给C。 例如,你想在C语言中使用某个Python函数作为一个回调。
解决方案解决方案
在C语言中调用Python非常简单,不过涉及到一些小窍门。 下面的C代码告诉你怎样安全的调用:
#include <Python.h>
/* Execute func(x,y) in the Python interpreter. The
arguments and return result of the function must be Python floats */
double call_func(PyObject *func, double x, double y) {
PyObject *args; PyObject *kwargs; PyObject *result = 0; double retval;
/* Make sure we own the GIL */ PyGILState_STATE state = PyGILState_Ensure();
/* Verify that func is a proper callable */ if (!PyCallable_Check(func)) {
fprintf(stderr,”call_func: expected a callablen”); goto fail;
} /* Build arguments */ args = Py_BuildValue(“(dd)”, x, y); kwargs = NULL;
/* Call the function */ result = PyObject_Call(func, args, kwargs); Py_DECREF(args); Py_XDECREF(kwargs);
/* Check for Python exceptions (if any) */ if (PyErr_Occurred()) {
PyErr_Print(); goto fail;
}
/* Verify the result is a float object */ if (!PyFloat_Check(result)) {
fprintf(stderr,”call_func: callable didn't return a floatn”); goto fail;
}
/* Create the return value */ retval = PyFloat_AsDouble(result); Py_DECREF(result);
/* Restore previous GIL state and return */ PyGILState_Release(state); return retval;
fail:
Py_XDECREF(result); PyGILState_Release(state); abort(); // Change to something more appropriate
}
要使用这个函数,你需要获取传递过来的某个已存在Python调用的引用。 有很多种方法可以让你这样做, 比如将一个可调用
对象传给一个扩展模块或直接写C代码从已存在模块中提取出来。
下面是一个简单例子用来展示从一个嵌入的Python解释器中调用一个函数:
#include <Python.h>
/* Definition of call_func() same as above */
...
/* Load a symbol from a module */
PyObject *import_name(const char *modname, const char *symbol) {
PyObject *u_name, *module;
u_name = PyUnicode_FromString(modname);
module = PyImport_Import(u_name);
Py_DECREF(u_name);
return PyObject_GetAttrString(module, symbol);
}
/* Simple embedding example */
int main() {
PyObject *pow_func;
double x;
Py_Initialize();
/* Get a reference to the math.pow function */