Search This Blog

Labels

Friday, December 17, 2010

《扩展和嵌入Python解释器(译稿)》1.1 A Simple Example

1.1 A Simple Example 一个简单的示例

Let’s create an extension module called ‘spam’ (the favorite food of Monty Python fans…) and let’s say we want to create a Python interface to the C library function system().1This function takes a null-terminated character string as argument and returns an integer. We want this function to be callable from Python as follows:

我们来创建一个名为‘spam’的扩展模块(spam 是 Monty Python 粉丝最爱的食物…)并且我们想要为 C 库函数:system()1 创建一个Python 的接口函数。该函数接收一个空终止字符串(以\0表示结尾的字符串)为参数,并返回一个整数。我们想要该函数在Python 中能以如下的方式调用:

>>> import spam

>>> status = spam.system("ls –l")

Begin by creating a file ‘spammodule.c’. (Historically, if a module is called ‘spam’, the C file containing its implementation is called ‘spammodule.c’; if the module name is very long, like ‘spammify’, the module name   can be just ‘spammify.c’.)

由创建文件 ‘spammodule.c’ 而开始。(传统地,如果一个模块名为 ‘spam’则其C 实现的文件名为‘spammodule.c’;如果模块名非常长,例如 ‘spammify’那么模块名也可以为‘spammify.c’)

The first line of our file can be:

我们程序的第一行可以是:

#include <Python.h>

which pulls in the Python API (you can add a comment describing the purpose of the module and a copyrigh tnotice if you like).

它引入 Python API (如果愿意,你也可以在这添加注释文字描述模块的用途和版权声明)

Warning: Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include ‘Python.h’ before any standard headers are included.

警告:在一些系统上,由于 Python 可能会定义一些影响标准头文件的预处理命令,你必须在包含任何标准头文件之前包含 ‘Python.h’ 。

All user-visible symbols defined by ‘Python.h’ have a prefix of ‘Py’ or ‘PY’, except those defined in standard header files. For convenience, and since they are used extensively by the Python interpreter, "Python.h"includes a few standard header files: <stdio.h>,<string.h>, <errno.h>, and <stdlib.h>.  If the latter header file does not exist on your system, it declares the functions malloc(), free()and realloc()directly.

所有由 ‘Python.h’ 定义的用户可见的符号都有一个‘Py’或‘PY’的前缀,除非那些在标准头文件中定义的。为方便起见,并且由于被 Python解释器广泛应用,”Python.h”文件包含了<stdio.h>,<string.h>,<errno.h>,和<stdlib.h>这些标准头文件。如果你的操作系统没有这些头文件,将直接地声明函数:malloc(),free()和realloc()。

The next thing we add to our module file is the C function that will be called when the Python expression ‘spam.system(string)’ is evaluated (we’ll see shortly how it ends up being called):

接下来添加到我们的模块文件的是当Python表达式:‘spam.system(string)’被执行时将被调用的 C函数

static PyObject *

spam_system(PyObject *self, PyObject *args)

{

    const char *command;

    int sts;

    if (!PyArg_ParseTuple(args, "s", &command))

       return NULL;

    sts = system(command);

    return Py_BuildValue("i", sts);

}

There is a straightforward translation from the argument list in Python (for example, the single expression "ls -l") to the arguments passed to the C function. The C function always has two arguments, conventionally namedselfand args.

在 Python 参数列表与传入 C 函数的参数之间有一个直观的转换。C 函数总是有两个参数,依惯例地命名为:selfargs

The self argument is only used when the C function implements a built-in method, not a function. In the example, self will always be a NULL pointer, since we are defining a function, not a method. (This is done so that the interpreter doesn’t have to understand two different types of C functions.)

self 参数仅仅用于当C函数是用来实现 Python 的一个内建方法而不是函数时。在这个例子中一直是一个空指针,因为我们定义的是一个函数而不是方法(这样做是为了使解释器没必要处理两种不同类型的 C 函数)

The argsargument will be a pointer to a Python tuple object containing the arguments. Each item of the tuple corresponds to an argument in the call’s argument list. The arguments are Python objects—in order to do anything with them in our C function we have to convert them to C values. The function PyArg_ParseTuple()in the Python API checks the argument types and converts them to C values. It uses atemplate string to determine the required types of the arguments as well as the types of the C variables into which to store the converted values. More about this later.

args 参数是一个指向存储了参数的 Python 元组的指针,元组中的每一个元素都对应了参数调用列表中的一个参数。这些参数是Python 对象——为了在我们的 C 函数中对它们进行操作,我们必须将它们转换成 C中的值。Python API 中的PyArg_ParseTuple()函数检查参数的类型并转换为 C 中的值。用一个转换码(template string)来确定要求的 Python参数以及用于存储转换值的 C 变量的类型。在后面可以了解更多。

PyArg_ParseTuple() returns true (nonzero) if all arguments have the right type and its components have been stored in the variables whose addresses are passed. It returns false (zero) if an invalid argument list was passed.   In the latter case it also raises an appropriate exception so the calling function can return NULLimmediately (as we saw in the example).

如果所有的参数类型正确且参数的值已经存储在其地址已传入PyArg_ParseTuple()函数的C变量中,则PyArg_ParseTuple()函数返回true(非零值);如果传入的是一个无效的参数列表,则返回false(零值)。后一种情况下,还会抛出合适的异常,所以函数调用能即时地返回一个 NULL指针(正如我们在示例中所见的)。

—————————————————————————————————————————————————————————————————

1An interface for this function already exists in the standard module os— it was chosen as a simple and straightforward example.

1这个函数的一个接口函数已经存在于标准模块——选择这个是为了作一个直观的示例。

No comments:

Post a Comment