Python编程
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 文件,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 for 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 for Microsoft Windows 构建
Microsoft Windows 用户可以使用 MinGW 从命令行编译扩展模块。假设 gcc
在路径中,你可以按如下方式构建扩展:
python setup.py build -c mingw32
上述命令将生成文件 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 的版本,例如 2.4 版本为“24”。
使用 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”。
fibmodule.c
中的 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 下载页面提供的二进制文件。
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!