使用C语言来扩展Python程序和Zope服务器的教程

论坛 期权论坛     
niminba   2021-5-22 16:52   251   0
<p>有几个原因使您可能想用 C 扩展 Zope。最可能的是您有一个已能帮您做些事的现成的 C 库,但是您对把它转换成 Python 却不感兴趣。此外,由于 Python 是解释性语言,所以任何被大量调用的 Python 代码都将降低您的速度。因此,即使您已经用 Python 写了一些扩展,您仍然要考虑把其中最常被调用的部分改用 C 来写。不论哪种方式,扩展 Zope 都是从扩展 Python 开始。此外,扩展 Python 会给您带来其它的好处,因为您的代码将可以从任何 Python 脚本访问,而不只是从 Zope。这里唯一要提醒的是在写本文的时候,Python 的当前版本是 2.1,但是 Zope 仍然只能和 Python 1.5.2 一起运行。对 C 扩展来说,两个版本并没有什么变化,但如果您有兴趣对您的库进行 Python 包装,又想让它们都能在 Zope 下工作,您就得注意不要使用任何比 1.5.2 更新的东西。<br>
<strong>Zope 是什么?</strong></p>
<p>Zope 代表“Z Object Publishing Environment(Z 对象发布环境)”,它是用 Python 实现的应用程序服务器。“太棒了,”您说,“但应用程序服务器的确切含义是什么呢?”应用程序服务器就是一个长期运行的进程,它为“活动的内容”提供服务。Web 服务器在运行期间调用应用程序服务器来构建页面。<br>
<strong>扩展 Python:有趣又有益</strong></p>
<p>想扩展 Zope,您首先要扩展 Python。虽然扩展 Python 不像“脑外科手术”那样复杂,但也不像“在公园中散步”那样悠闲。有两个基本组件用于 Python 扩展。第一个显然是 C 代码。我将马上探讨它。 另一个部分是 安装文件。安装文件通过提供模块名称、模块的 C 代码的位置和您可能需要的所有编译器标志来描述模块。该文件被预处理,以创建 makefile(在 UNIX 上)或 MSVC++ 工程文件(MSVC++ project file,在 Windows 上)。先说一下 ― Windows 上的 Python 事实上是用 Microsoft 编译器编译的。Python.org 的人也推荐用 MSVC++ 编译扩展。显然,您应该能够成功说服 GNU 的编译者们,但我本人还没试过。</p>
<p>无论如何,还是让我们来定义一个叫做‘foo'的模块吧。‘foo'模块会有一个叫做‘bar'的函数。当我们要使用时,我们可以用 import foo; 来把这个函数导入到 Python 脚本中,就跟导入任何模块一样。安装文件非常简单:<br>
清单 1. 一个典型的安装文件</p>
<div class="blockcode">
<pre class="brush:py;">
# You can include comment lines. The *shared* directive indicates
# that the following module(s) are to be compiled and linked for
# dynamic loading as opposed to static: .so on Unix, .dll on Windows.
*shared*
# Then you can use the variables later using the $(variable) syntax
# that 'make' uses. This next line defines our module and tells
# Python where its source code is.
foo foomain.c

</pre>
</div>
<p><strong>编写代码</strong></p>
<p>那么我们实际上该怎样写 Python 知道如何使用的代码呢,您问? foomain.c (当然,您可以随意命名它)文件包含三项内容:一个方法表,一个初始化函数和其余的代码。方法表简单地将函数名与函数联系起来,并告知 Python 各个函数所使用的参数传递机制(您可以选择使用一般的位置参数列表或位置参数和关键词参数的混合列表)。Python 在模块装入时调用初始化函数。初始化函数将完成模块所要求的所有初始化操作,但更重要的是,它还把一个指向方法表的指针传回给 Python。</p>
<p>那我们就来看看我们的小型 foo 模块的 C 代码。<br>
清单 2. 一个典型的 Python 扩展模块</p>
<div class="blockcode">
<pre class="brush:cpp;">
#include &lt;Python.h&gt;
/* Define the method table. */
static PyObject *foo_bar(PyObject *self, PyObject *args);
static PyMethodDef FooMethods[] = {
  {"bar", foo_bar, METH_VARARGS},
  {NULL, NULL}
};
/* Here's the initialization function. We don't need to do anything
  for our own needs, but Python needs that method table. */
void initfoo()
{
  (void) Py_InitModule("foo", FooMethods);
}
/* Finally, let's do something ... involved ... as an example function. */
static PyObject *foo_bar(PyObject *self, PyObject *args)
{
  char *string;
  int  len;
  if (!PyArg_ParseTuple(args, "s", &amp;string))
    return NULL;
  len = strlen(string);
  return Py_BuildValue("i", len);
}

</pre>
</div>
<p><strong>深入研究</strong></p>
<p>我们来看会儿这些代码。首先,请注意您必须包含 Python.h 。除非您已在包含路径(include path)中设置了该文件的路径,否则您可能需要在安装文件中包含 -I 标志以指向该文件。</p>
<p>初始化函数必须命名为 init &lt;模块名&gt;,在我们的例子中是 initfoo 。初始化函数的名称,毫无疑问,是 Python 在装入模块时所知道的关于模块的全部信息,这也是初始化函数的名称如此死板的原因。顺便说一下,初始化函数必须是文件中唯一未被声明为 static 的全局标识符。这对静态链接比对动态链接更重要,因为非 static 标
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP