Search This Blog

Labels

Friday, December 17, 2010

《扩展和嵌入Python解释器(译稿)》1.6 Calling Python Functions from C

1.6 Calling Python Functions from C 在C中调用Python函数

So far we have concentrated on making C functions callable from Python. The reverse is also useful: calling Python functions from C. This is especially the case for libraries that support so-called “callback” functions. If   a C interface makes use of callbacks, the equivalent Python often needs to provide a callback mechanism to the Python programmer; the implementation will require calling the Python callback functions from a C callback. Other uses are also imaginable.

到目前为止,我们专注于使C 函数在Python中可调用。其逆过程:从C 中调用Python函数,也同样有用,尤其是对于支持“回调函数”的库来说。如果一个C接口利用到了回调,Python中相应的函数经常需要为Python程序员提供一个回调机制,这样的实现需要从C中调用Python中的回调函数,其他的用法同样可以想象。

Fortunately, the Python interpreter is easily called recursively, and there is a standard interface to call a Python function. (I won’t dwell on how to call the Python parser with a particular string as input — if you’re interested, have a look at the implementation of the -c command line option in ‘Python/pythonmain.c’ from the Python source code.)

幸运的是,Python解释器可以容易地被递归调用,并且还有一个标准的接口用来调用Python函数。(我无意详述如何以一特定的字符串为输入来调用Python 解析器——如果你有兴趣,可以在Python源码中的‘Python/pythonmain.c’看看-c命令行选项的实现。)

Calling a Python function is easy. First, the Python program must somehow pass you the Python function object. You should provide a function (or some other interface) to do this. When this function is called, save a pointer to the Python function object (be careful to Py_INCREF() it!) in a global variable — or wherever you see fit. For example, the following function might be part of a module definition:

调用Python函数是容易的。首先,Python程序必须以某种方式传递Python函数对象给你。你应该提供一个函数(或其他的一些接口)来这样做。当这个函数被调用时,保存一个指向Python函数对象的指针(要注意用Py_INCREF()作用一下!)到全局变量中——或任何你觉得合适的地方。例如,下面的函数可能是某模块的定义的一部分。

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);         /* Add a reference to new callback */

        Py_XDECREF(my_callback); /* Dispose of previous callback */

        my_callback = temp;       /* Remember new callback */

        /* Boilerplate to return "None" */

        Py_INCREF(Py_None);

        result = Py_None;

    }

return result;

}

This function must be registered with the interpreter using the METH_VARARGS flag; this is described in section 1.4, “The Module’s Method Table and Initialization Function.” ThePyArg_ParseTuple() function and its arguments are documented in section 1.7, “Extracting Parameters in Extension Functions.”

该函数必须使用METH_VARARGS标识与解释器注册,这在1.4节“模块的方法列表和初始化函数”也讲到了。PyArg_ParseTuple()函数及其参数在1.7节“在扩展函数中析取参数”中讲到了

The macros Py_XINCREF()and Py_XDECREF()increment/decrement the reference count of an object and   are safe in the presence of NULLpointers (but note that temp will not beNULLin this context). More info on them in section 1.10, “Reference Counts.”

宏Py_XINCREF()和Py_XDECREF()增加/减少对象的引用计数,并且在空(NULL)指针出现时也是安全的(但要注意到,在上面那段代码中temp不会是NULL)。更多相关信息在1.10节“引用计数”。

Later, when it is time to call the function, you call the C function PyEval_CallObject(). This function   has two arguments, both pointers to arbitrary Python objects: the Python function, and the argument list. The argument list must always be a tuple object, whose length is the number of arguments. To call the Python function with no arguments, pass an empty tuple; to call it with one argument, pass a singleton tuple. Py_BuildValue() returns a tuple when its format string consists of zero or more format codes between parentheses. For example:

随后,当调用函数时,你调用C 函数PyEval_CallObject()。这个函数有两个参数:Python对象和参数列表,两者都是指向任意Python 对象的指针。参数列表必须是一个元组对象,其长度为参数个数。无参数调用Python函数时传入一个空元组;以一个参数调用时传入一个单元素元组。当其格式码包含0或者更多的格式码时,Py_BuildValue()返回一个元组。例如:

int arg;

PyObject *arglist;

PyObject *result;

arg = 123;

/* Time to call the callback */

arglist = Py_BuildValue("(i)", arg);

result = PyEval_CallObject(my_callback, arglist);

Py_DECREF(arglist);

PyEval_CallObject() returns a Python object pointer: this is the return value of the Python function. PyEval_CallObject()is “reference-count-neutral” with respect to its arguments. In the example a new tuple was created to serve as the argument list, which isPy_DECREF()-ed immediately after the call.

PyEval_CallObject()返回一个指向Python对象的指针:这是Python函数的返回值。对于其参数是“引用计数中立”的。在这个例子中,一个新的元组被创建以充当参数列表,在调用之后立即用Py_DECREF()操作。

The return value of PyEval_CallObject()is “new”: either it is a brand new object, or it is an existing object whose reference count has been incremented. So, unless you want to save it in a global variable, you should somehow Py_DECREF()the result, even (especially!) if you are not interested in its value.

PyEval_CallObject()的返回值是“新”的:要么是一个全新的对象,要么就是一个引用计数增加了的现有对象。所以,除非你想将它保存进一个全局变量,你应该以某种方式用Py_DECREF()操作返回结果,甚至是(特别是!)如果你对返回结果的值不感兴趣。

Before you do this, however, it is important to check that the return value isn’t NULL. If it is, the Python function terminated by raising an exception. If the C code that calledPyEval_CallObject()is called from Python, it should now return an error indication to its Python caller, so the interpreter can print a stack trace, or the calling Python code can handle the exception. If this is not possible or desirable, the exception should be cleared by callingPyErr_Clear().For example:

在你这样做之前,然而,确认返回值不为空(NULL)是很重要的。若为空的话,则抛出一个异常,Python函数被终止。如果调用PyEval_CallObject()的C 代码是在Python中被调用,它将返回一个错误指示值给它的Python调用者,因此解释器或者打印出栈追踪信息,或者Python代码能处理发生的异常。如果不能处理或不能描述,异常就应当通过调用PyErr_Clear()来清除。例如:

if (result == NULL)

return NULL; /* Pass error back */

…use result…

Py_DECREF(result);

Depending on the desired interface to the Python callback function, you may also have to provide an argument list to PyEval_CallObject(). In some cases the argument list is also provided by the Python program, through the same interface that specified the callback function. It can then be saved and used in the same manner as the function object. In other cases, you may have to construct a new tuple to pass as the argument list. The simplest way to do this is to callPy_BuildValue(). For example, if you want to pass an integral event code, you might use the following code:

随Python回调函数的目标接口而定,你可能还必须提供一个参数列表给PyEval_CallObjec t()。尽管与指定回调函数的接口相同,在有些情况下参数列表也可由Python 程序提供。在另外的情况下,你可能必须构建一个新的元组以作为参数列表传入。最简单的方式就是调用Py_BuildValue()。例如,如果你想传入一段必须的事件代码,你可能使用下面的代码:

PyObject *arglist;

arglist = Py_BuildValue("(l)", eventcode);

result = PyEval_CallObject(my_callback, arglist);

Py_DECREF(arglist);

if (result == NULL)

    return NULL; /* Pass error back */

/* Here maybe use the result */

Py_DECREF(result);

Note the placement of ‘Py_DECREF(arglist)’ immediately after the call, before the error check! Also note that strictly spoken this code is not complete: Py_BuildValue() may run out of memory, and this should be checked.

注意到在错误检测之前,‘Py_DECREF(arglist)’紧接着调用之后出现。还应注意到,严格地来说这段代码并不完整:可能耗尽内存,这应该要检测。

No comments:

Post a Comment