一. SWIG簡(jiǎn)介:
SWIG是Simple Wrapper and Interface Generator的縮寫,是一個(gè)幫助使用C或者C++編寫的軟件創(chuàng)建其他編語(yǔ)言的API的工具。例如,我想要為一個(gè)C++編寫的程序創(chuàng)建.NET API,一般情況下我必須使用托管C++(Managed C++)去編寫大量的代碼才能生成它的.NET API。有了SWIG,這個(gè)機(jī)械的工作將變得非常簡(jiǎn)單。你只須要使用一個(gè)接口文件告訴SWIG要為那些類創(chuàng)建.NET API,SWIG就會(huì)自動(dòng)幫你生成它的.NET API。
當(dāng)然,SWIG不僅僅支持創(chuàng)建.NET API。最新版本的SWIG支持常用腳本語(yǔ)言Perl、PHP、Python、Tcl、Ruby和非腳本語(yǔ)言C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Modula-3, OCAML以及R,甚至是編譯器或者匯編的計(jì)劃應(yīng)用(Guile, MzScheme, Chicken)。
二. 環(huán)境搭建
1. 下載swigwin,在E:/lib目錄下解壓,即把swig安裝到E:/lib/swig目錄中。
2. 新建一個(gè)Win32 Console Application,注意在Application Settings中選擇DLL以及空項(xiàng)目。完成后將工程的配置改成release
3. 工具 —> 選項(xiàng) —> 項(xiàng)目和解決方案 —> VC++目錄 —> 添加E:/lib/swigwin。即把swig添加到VC的可執(zhí)行目錄。
----------------若封裝成Python可用的API,執(zhí)行如下步驟----------------------------
4. 下載python2.5,安裝到D:/Program Files目錄,并在環(huán)境變量PATH中加入D:/Program Files/python2.5。
5. 把D:/Program Files/python2.5/include加入VC的Include路徑,將D:/Program Files/python2.5/libs加入VC的Library路徑。
-----------------若封裝成Java可用的API,執(zhí)行如下步驟--------------------------------
6. 下載JDK,安裝到D:/Program Files目錄,并在環(huán)境變量PATH中加入D:/Program Files/Java/jdk1.6.0_10/bin(如果之前安裝過(guò)Oracle,要將D:/Program Files/Java/jdk1.6.0_10/bin放在Oracle/jre/1.3.1/bin前面,否則在編譯的時(shí)候默認(rèn)會(huì)選擇oracle的jdk)
7. 把D:/Program Files/Java/jdk1.6.0_10/include/win32 和 D:/Program Files/Java/jdk1.6.0_10/include 加入到加入VC的Include路徑。
三. 接口文件
要在C/C++工程中創(chuàng)建***.i 的接口文件,告訴SWIG要為那些類的那些方法創(chuàng)建API。
接口文件注解:
1. 模塊名由指定的%module來(lái)給出(或者用-module命令行選項(xiàng)).這段指示性文字必須寫在文件的頭部并且在使用時(shí)將這個(gè)模塊名作為擴(kuò)展模塊對(duì)象來(lái)使用(此外,這個(gè)模塊名經(jīng)常在目標(biāo)語(yǔ)言中被定義成一個(gè)命名空間來(lái)使用)。如果模塊名在命令行已經(jīng)被給出了,系統(tǒng)將不考慮由%module標(biāo)示的模塊名了。
對(duì)于python:module的名字指定了生成文件xxx.py的xxx名字,
對(duì)于java:module的名字指定了生成文件xxx.java的xxx名字
2. 所有在%{...%}塊內(nèi)的東西將被簡(jiǎn)單作為結(jié)果逐字拷貝到SWIG創(chuàng)建的wrapper(包裝)文件中。這部分大部分被用來(lái)包括頭文件和生成wrapper代碼需要的其它聲明。這里很重要的強(qiáng)調(diào)一點(diǎn)因?yàn)槟阍谝粋€(gè)SWIG的輸入文件中包含了一個(gè)聲明,這個(gè)聲明并不自動(dòng)顯示在生成的wrapper代碼中,因此你需要確信你確實(shí)把正確的頭文件在%{ ... %}部分中。這里應(yīng)該指出SWIG不解析和解釋附在%{ ... %}部分的文字。SWIG的%{...%}內(nèi)的語(yǔ)法和語(yǔ)義很類似于輸入文件中的聲明部分 。
3. 如果打算為類中所有方法創(chuàng)建API,那么有一個(gè)非常簡(jiǎn)單的辦法,在接口文件的類聲明部分使用%include標(biāo)記。SWIG將對(duì)%include所指定的文件進(jìn)行語(yǔ)法分析,類中所有公有方法(Public Method)都將在API中暴露。
/* SwigTest.i */
%module SwigTest
%{
#include "SwigTest.h"
%}
%include “SwigTest.h” //不要和#用混
-------------------------- swig庫(kù)模塊訪問(wèn)部分標(biāo)準(zhǔn)C++庫(kù)包括STL的方法-------------------
SWIG對(duì)于一些語(yǔ)言模塊的支持使較全面的但是對(duì)很少用到的庫(kù)則支持的很少。
下面就是表示了C++類和支持的C++庫(kù) 以及SWIG接口文件的對(duì)應(yīng)表
C++ class C++ Library file SWIG Interface library file
std::deque deque std_deque.i
std::list list std_list.i
std::map map std_map.i
std::pair utility std_pair.i
std::set set std_set.i
std::string string std_string.i
std::vector vector std_vector.i
因此,當(dāng)C / C++代碼中用到這些庫(kù)時(shí),可將swig對(duì)應(yīng)的接口文件添加到自己的接口文
件中。如:%include "std_string.i",
庫(kù)文件完全識(shí)別C++的命名空間。如果你輸出std::string 或 將它重命名為另一種類型。請(qǐng)確認(rèn)你將此重命名聲明包含到了你的接口文件中。例如:
%module example
%include "std_string.i"
using namespace std;
typedef std::string String;
...
void foo(string s, const String &t); // std_string typemaps still applied
當(dāng)封裝java調(diào)用的api且傳遞的參數(shù)中含有中文時(shí),由于c++中的String是使用單字節(jié)編碼,而java中String是使用Unicode編碼,所以為了傳遞時(shí)不出現(xiàn)亂碼,可以包含%include "std_wstring.i",因?yàn)閣string使用的是wchar_t類型,這是寬字符,用于滿足非ASCII字符的要求,例如Unicode編碼。
當(dāng)封裝python調(diào)用的api且傳遞的參數(shù)中含有中文時(shí),就不用考慮這個(gè)編碼問(wèn)題,可以直接使用c++中的String。
四. 編譯模塊
1.寫接口執(zhí)行命令
有了接口文件以后要對(duì)接口文件進(jìn)行編譯,右鍵點(diǎn)擊接口文件,修改它的屬性,使用自定義編譯工具(Custom Build Tool),命令行(Command Line)內(nèi)容為swig.exe -c++ -python SwigTest.i ,輸出(Outputs)為$(InputName)_wrapper.cpp;
echo JAVA_INCLUDE: %JAVA_INCLUDE%
echo JAVA_BIN: %JAVA_BIN%
echo on
swig.exe -c++ -python SwigTest.i
命令行參數(shù)說(shuō)明:
① 為了編譯java 或python模塊,必須包含它們的include和bin目錄,可以在PATH中設(shè)置JAVA_INCLUDE、JAVA_BIN、PYTHON_INCLUDE、PYTHON_BIN等,其中include可以在工程屬性中設(shè)置,如果工程屬性中已經(jīng)設(shè)置好,此處不用再包含頭兩句。
②“ swig.exe ”表示調(diào)用你安裝的swig的可執(zhí)行文件,之前已經(jīng)將其目錄加入到VC的可執(zhí)行目錄中,所以此處就可以不用再寫路徑,否則要找到swig路徑才行。
③ “-c++” 表示要封裝C++代碼(不寫默認(rèn)是封裝C代碼),
④“-python”表示要封裝成Python接口(Swig還可以封裝成Java、Ruby等接口),
⑤ “$(InputName)_wrapper.cpp”表示指定要生成的C++代碼文件的名字。
swig的命令還有其他的一些,目前用到的如 –package命令,用法可以為:
swig -java -package com.swig -outdir com/swig example.i
在生成java的api時(shí),這個(gè)命令使生成的java文件包含在某個(gè)包中。
2.編譯(右鍵點(diǎn)擊接口文件—>編譯)
對(duì)于生成python可用的API:執(zhí)行上述命令會(huì)生成兩個(gè)新的文件,一個(gè)是SwigTest.py,一個(gè)是SwigTest_wrapper.cpp。
對(duì)于生成java可用的API:執(zhí)行上述命令會(huì)生成Java類文件:SwigTestJNI.java,SwigTest.java
和c文件SwigTest_wrapper.cpp。
3.將xxx_wrapper.cpp加入到工程
4.修改工程屬性:
-----------------------封裝java可用的api---------------------
LinkeràGeneralàOutput File改成SwigTest.dll
Build EventsàPost-Build EventàCommand Line改成:
echo on
"%JAVA_BIN%/javac" *.java
這個(gè)命令作用是編譯完后調(diào)用javac將當(dāng)前編譯路徑下的所有.java文件編譯成.class二進(jìn)制文件。
-----------------------封裝python可用的api---------------------
LinkeràGeneralàOutput File改成_SwigTest.pyd(注意一定要有下劃線)
還有一些配置在VC2005里是默認(rèn)的,但在VC2003里不是的,請(qǐng)引起注意,包括
① C/C++àCode GenerationàRuntime Library要選擇Multi-threaded DLL (/MD)
② C/C++àLanguageàTreat wchar_t as Built-in Type要選擇yes(如果轉(zhuǎn)換不涉及wchar等,則無(wú)需處理這一項(xiàng))
③ C/C++àLanguageàEnable Run-Time Type Info要選擇yes
5.生成工程
五.利用生成的api就可以在對(duì)應(yīng)的腳本語(yǔ)言(java、python等)中使用啦。
windows環(huán)境2.0.7版:http://prdownloads.sourceforge.net/swig/swigwin-2.0.7.zip
(###)
聯(lián)系客服