Python 编程/使用 C 扩展
Python 模块可以使用纯 Python 编写,也可以使用 C 语言编写。以下展示了如何使用 C 扩展 Python。
为了说明机制,我们将创建一个包含单个函数的最小扩展模块,该函数输出 "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])
然后我们可以使用一个过程来构建模块,该过程的详细信息取决于操作系统和编译器套件。
在编译模块之前,您必须安装 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.
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 版。
对于 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 是一个工具,可以帮助各种脚本和编程语言调用 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!
- 扩展和嵌入 Python 解释器,python.org
- Python/C API 参考手册,python.org
- SWIG,swig.org
- 下载 SWIG,swig.org