跳转到内容

Python 编程/使用 C 扩展

来自维基教科书,开放的书籍,开放的世界


Python 模块可以使用纯 Python 编写,也可以使用 C 语言编写。以下展示了如何使用 C 扩展 Python。

使用 Python/C API

[编辑 | 编辑源代码]

一个最小的例子

[编辑 | 编辑源代码]

为了说明机制,我们将创建一个包含单个函数的最小扩展模块,该函数输出 "Hello" 后跟作为第一个参数传递的名称。

我们将首先创建 C 源代码,并将其放置到 hellomodule.c

#include <Python.h>

static PyObject*
say_hello(PyObject* self, PyObject* args)
{
    const char* name;

    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;

    printf("Hello %s!\n", name);

    Py_RETURN_NONE;
}

static PyMethodDef HelloMethods[] =
{
     {"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
inithello(void)
{
     (void) Py_InitModule("hello", HelloMethods);
}

然后我们需要一个安装文件,setup.py

from distutils.core import setup, Extension

module1 = Extension('hello', sources = ['hellomodule.c'])

setup (name = 'PackageName',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [module1])

然后我们可以使用一个过程来构建模块,该过程的详细信息取决于操作系统和编译器套件。

使用 GCC 在 Linux 上构建

[编辑 | 编辑源代码]

在编译模块之前,您必须安装 Python 开发头文件,如果您还没有安装的话。在 Debian 和基于 Debian 的系统(如 Ubuntu)上,可以使用以下命令安装这些头文件

$ sudo apt install python-dev

在 openSUSE 上,所需软件包名为 python-devel,可以使用 zypper 安装

$ sudo zypper install python-devel


现在 Python.h 可用了,我们可以使用以下命令编译上一节中创建的模块源代码

$ python setup.py build

这将编译模块到名为hello.so的文件中,位于build/lib.linux-i686-x.y.

使用 GCC 在 Microsoft Windows 上构建

[编辑 | 编辑源代码]

Microsoft Windows 用户可以使用 MinGW 从命令行编译扩展模块。假设gcc在路径中,您可以使用以下命令构建扩展

python setup.py build -cmingw32

以上将生成文件hello.pyd,一个 Python 动态模块,类似于 DLL。该文件将位于build\lib.win32-x.y.

在 Windows 中构建模块的另一种方法是构建一个 DLL。(这种方法不需要扩展模块文件)。从cmd.exe,输入

gcc -c  hellomodule.c -I/PythonXY/include
gcc -shared hellomodule.o -L/PythonXY/libs -lpythonXY -o hello.dll

其中 XY 表示 Python 的版本,例如 "24" 表示 2.4 版。

使用 Microsoft Visual C++ 构建

[编辑 | 编辑源代码]

对于 VC8,distutils 出现了问题。因此,我们将使用命令提示符中的 cl.exe

cl /LD hellomodule.c /Ic:\Python24\include c:\Python24\libs\python24.lib /link/out:hello.dll

使用扩展模块

[编辑 | 编辑源代码]

切换到 hello.so 文件所在的子目录。在交互式 Python 会话中,您可以按如下方式使用该模块。

>>> import hello
>>> hello.say_hello("World")
Hello World!

用于计算斐波那契数列的模块

[编辑 | 编辑源代码]

在本节中,我们将介绍一个用于斐波那契数列的模块,从而扩展了上面的最小示例。与最小示例相比,值得注意的是在 PyArg_ParseTuple() 和 Py_BuildValue() 中使用了 "i"。

C 源代码(fibmodule.c)

#include <Python.h>

int
_fib(int n)
{
    if (n < 2)
        return n;
    else
        return _fib(n-1) + _fib(n-2);
}

static PyObject*
fib(PyObject* self, PyObject* args)
{
    int n;

    if (!PyArg_ParseTuple(args, "i", &n))
        return NULL;

    return Py_BuildValue("i", _fib(n));
}

static PyMethodDef FibMethods[] = {
    {"fib", fib, METH_VARARGS, "Calculate the Fibonacci numbers."},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initfib(void)
{
    (void) Py_InitModule("fib", FibMethods);
}

构建脚本(setup.py)

from distutils.core import setup, Extension

module1 = Extension('fib', sources = ['fibmodule.c'])

setup (name = 'PackageName',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [module1])

使用

>>> import fib
>>> fib.fib(10)
55

使用 SWIG

[编辑 | 编辑源代码]

SWIG 是一个工具,可以帮助各种脚本和编程语言调用 C 和 C++ 代码。SWIG 使得创建 C 语言模块变得更加直接。

要使用 SWIG,您需要先将其启动并运行。

您可以在 Ubuntu 系统上按如下方式安装它

$ sudo apt-get install swig
$ sudo apt-get install python-dev

要获取适用于 Windows 的 SWIG,您可以使用 SWIG 下载页面提供的二进制文件。

安装完 SWIG 后,您需要创建模块源文件和模块接口文件

hellomodule.c

#include <stdio.h>

void say_hello(const char* name) {
    printf("Hello %s!\n", name);
}

hello.i

%module hello
extern void say_hello(const char* name);

然后我们让 SWIG 完成它的工作

swig -python hello.i

以上会生成文件 hello.py 和 hello_wrap.c。

下一步是编译;将 /usr/include/python2.4/ 替换为您设置中 Python.h 的正确路径

gcc -fpic -c hellomodule.c hello_wrap.c -I/usr/include/python2.4/

最后一步是链接

gcc -shared hellomodule.o hello_wrap.o -o _hello.so -lpython

模块的使用方法如下

>>> import hello
>>> hello.say_hello("World")
Hello World!
[编辑 | 编辑源代码]
华夏公益教科书