Python 實(shí)在是一種讓人上癮的編程語(yǔ)言羽杰,簡(jiǎn)潔的語(yǔ)法+豐富的擴(kuò)展包屎慢,幾乎可以用 Python 做任何事情瞭稼,唯一的黑點(diǎn)似乎就是「慢」忽洛,但是與高效的編譯語(yǔ)言 C\C++ 互聯(lián)以后腻惠,可以解決腳本語(yǔ)言運(yùn)行速度慢的問(wèn)題,甚至用來(lái)做一些計(jì)算密集型的工作欲虚,比如 CFD集灌。
這一篇介紹純 C 語(yǔ)言擴(kuò)展 Python。
為什么是swig复哆?
Python底層就是 C\C++欣喧,有原生的 C\C++ 接口,用來(lái)傳遞變量梯找,但是完全手寫中間層對(duì)于我這樣的業(yè)余 Coder 實(shí)在太痛苦了唆阿,這不是一件很有意思的工作。事實(shí)上锈锤,即使在Python的官方文檔里也推薦用第三方的接口工具處理驯鳖。
Third party tools like
Cython
,cffi
,SWIG
andNumba
offer both simpler and more sophisticated approaches to creating C and C++ extensions for Python.
除了以上的第三方工具外,還有 sip
,Boost.python
,pyrex
等好用的工具久免,在這篇 文章 里初步介紹了 C\C++ 擴(kuò)展Python的各種方法浅辙。
之前用過(guò)Boost.python
,可能是我之前沒(méi)接觸過(guò)Boost
吧阎姥,不是很喜歡记舆,感覺(jué)不夠輕量級(jí),然后對(duì)swig
一見(jiàn)傾心的原因是其對(duì)于純 C 的良好支持(當(dāng)時(shí)寫這篇文章的時(shí)候?qū)?C++ 莫名的反感呼巴,雖然現(xiàn)在已經(jīng)入了 C++ 的坑了)泽腮。
怎么安裝swig?
1.Mac OS
強(qiáng)烈建議用brew來(lái)裝
brew install swig
一條命令搞定衣赶,媽媽再也不用擔(dān)心你的依賴問(wèn)題了诊赊。
2.Windows
博主暫時(shí)脫離windows開(kāi)發(fā)環(huán)境一會(huì)兒,建議參考官方文檔
3.Linux
大名鼎鼎的apt-get install
怎么使用swig屑埋?
我參考了官方文檔里的一個(gè)示例程序豪筝,最終的目的是生成一個(gè)動(dòng)態(tài)鏈接庫(kù)和一個(gè)供調(diào)用的py
文件。
- 聲明函數(shù)先
創(chuàng)建一個(gè)example.h
頭文件來(lái)聲明這個(gè)函數(shù):
/*File: example.h*/
int fact(int n);
- 定義函數(shù)
創(chuàng)建一個(gè)example.c
的文件(用來(lái)計(jì)算n!
):
/* File: example.c */
#include "example.h"
int fact(int n) {
if (n < 0){
/* This should probably return an error, but this is simpler */
return 0; }
else if (n == 0) {
return 1;
}
else {
/* testing for overflow would be a good idea here */
return n * fact(n-1);
}
}
- 關(guān)鍵一步
我們還需要?jiǎng)?chuàng)建一個(gè)example.i
文件來(lái)配置swig
:
/* File: example.i */
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
int fact(int n);
簡(jiǎn)單解釋一下這個(gè)配置文件摘能,#define SWIG_FILE_WITH_INIT
宏規(guī)定這個(gè) C 文件將會(huì)被編譯成 Python 模塊续崖,#include "example.h"
給出需要包含的頭文件,最后一句在example.i
聲明了這個(gè)函數(shù)团搞,就是這么簡(jiǎn)單嘛严望。
有了這三個(gè)文件之后,我們需要先編譯出一個(gè) Python 文件逻恐,在終端運(yùn)行:
swig -python example.i
如果編譯的是C++文件像吻,需要加上-C++
選項(xiàng):
swig -c++ -python example.i
運(yùn)行完這個(gè)命令后峻黍,在工作目錄里會(huì)出現(xiàn)example_wrap.c
或example.cxx
以及一個(gè)example.py
的Python文件,但是現(xiàn)在這個(gè)模塊還不能直接調(diào)用拨匆,因?yàn)檫€缺少動(dòng)態(tài)鏈接庫(kù)姆涩,如果強(qiáng)行調(diào)用會(huì)出現(xiàn)這種錯(cuò)誤:
ImportError: No module named '_example'
接下來(lái)需要編譯出一個(gè)shared object file,在Linux平臺(tái)里是so
文件惭每,在windows下是Dll
文件骨饿,有兩種方法完成這個(gè)步驟,官方文檔中推薦使用distutils台腥,即Python的setup.py
生成模塊:
"""
setup.py file for SWIG example
"""
from distutils.core import setup, Extension
example_module = Extension('_example',
sources=['example_wrap.c', 'example.c'],
)
setup(name = 'example',
version = '0.1',
author = "SWIG Docs",
description = """Simple swig example from docs""",
ext_modules = [example_module],
py_modules = ["example"],
)
然后在終端里輸入:
python setup.py build_ext --inplace
build_ext
告訴Python需要編譯的是擴(kuò)展模塊宏赘,--inplace
會(huì)確保編譯生成的文件放在當(dāng)前目錄中。
運(yùn)行完這個(gè)命令后黎侈,會(huì)在工作目錄出現(xiàn)一個(gè)so
文件察署,這時(shí)example.py
文件可以直接被Python調(diào)用:
來(lái)自 Cescfangs 的博客:fangs.in