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