SWIG 3 中文手冊——2. 引言

2 引言

2.1 SWIG 是什麼?

SWIG is a software development tool that simplifies the task of interfacing different languages to C and C++ programs. In a nutshell, SWIG is a compiler that takes C/C++ declarations and creates the wrappers needed to access those declarations from other languages including Perl, Python, Tcl, Ruby, Guile, and Java. SWIG normally requires no modifications to existing code and can often be used to build a usable interface in only a few minutes. Possible applications of SWIG include:python

  • Building interpreted interfaces to existing C programs.
  • Rapid prototyping and application development.
  • Interactive debugging.
  • Reengineering or refactoring of legacy software into scripting language components.
  • Making a graphical user interface (using Tk for example).
  • Testing of C libraries and programs (using scripts).
  • Building high performance C modules for scripting languages.
  • Making C programming more enjoyable (or tolerable depending on your point of view).
  • Impressing your friends.
  • Obtaining vast sums of research funding (although obviously not applicable to the author).

SWIG was originally designed to make it extremely easy for scientists and engineers to build extensible scientific software without having to get a degree in software engineering. Because of this, the use of SWIG tends to be somewhat informal and ad-hoc (e.g., SWIG does not require users to provide formal interface specifications as you would find in a dedicated IDL compiler). Although this style of development isn't appropriate for every project, it is particularly well suited to software development in the small; especially the research and development work that is commonly found in scientific and engineering projects. However, nowadays SWIG is known to be used in many large open source and commercial projects.linux

SWIG 是一款軟件開發工具,它簡化了將不一樣語言鏈接到 C 和 C++ 程序的任務。簡而言之,SWIG 是一個編譯器,它接受 C/C++ 聲明並建立從其餘語言(包括 Perl、Python、Tcl、Ruby、Guile 和 Java)訪問這些聲明所需的包裝器。SWIG 一般不須要修改現有代碼,而且能夠在幾分鐘內構建可用的接口。SWIG 可能的應用包括:程序員

  • 構建現有 C 程序的解釋接口。
  • 快速原型設計和應用程序開發。
  • 交互式調試。
  • 將歷史遺留軟件從新設計或重構爲腳本語言組件。
  • 製做圖形用戶(例如使用 Tk)。
  • 測試 C 代碼庫和程序(使用腳本)。
  • 爲腳本語言構建高性能 C 模塊。
  • 使 C 編程更愉快(或視你的狀況而定)。
  • 給你的朋友留下深入印象
  • 得到大量研究經費(雖然顯然不適用於做者本人)。

SWIG 最初旨在使科學家和工程師可以很是輕鬆地構建可擴展的科學軟件,而無需軟件工程學位。所以,SWIG 的使用每每是非正式的和臨時的(例如,SWIG 不要求用戶提供正式的接口規範,就像你在專用的 IDL 編譯器中找到的那樣)。雖然這種開發方式並不適合每一個項目,但它特別適合於小型軟件開發,特別是科學和工程項目中常見的研究和開發工做。可是,現在已知 SWIG 可用於許多大型開源和商業項目。shell

2.2 爲何使用 SWIG?

As stated in the previous section, the primary purpose of SWIG is to simplify the task of integrating C/C++ with other programming languages. However, why would anyone want to do that? To answer that question, it is useful to list a few strengths of C/C++ programming:編程

  • Excellent support for writing programming libraries.
  • High performance (number crunching, data processing, graphics, etc.).
  • Systems programming and systems integration.
  • Large user community and software base.

Next, let's list a few problems with C/C++ programmingapi

  • Writing a user interface is rather painful (i.e., consider programming with MFC, X11, GTK, or any number of other libraries).
  • Testing is time consuming (the compile/debug cycle).
  • Not easy to reconfigure or customize without recompilation.
  • Modularization can be tricky.
  • Security concerns (buffer overflows for instance).

To address these limitations, many programmers have arrived at the conclusion that it is much easier to use different programming languages for different tasks. For instance, writing a graphical user interface may be significantly easier in a scripting language like Python or Tcl (consider the reasons why millions of programmers have used languages like Visual Basic if you need more proof). An interactive interpreter might also serve as a useful debugging and testing tool. Other languages like Java might greatly simplify the task of writing distributed computing software. The key point is that different programming languages offer different strengths and weaknesses. Moreover, it is extremely unlikely that any programming is ever going to be perfect. Therefore, by combining languages together, you can utilize the best features of each language and greatly simplify certain aspects of software development.安全

From the standpoint of C/C++, a lot of people use SWIG because they want to break out of the traditional monolithic C programming model which usually results in programs that resemble this:app

  • A collection of functions and variables that do something useful.
  • A main() program that starts everything.
  • A horrible collection of hacks that form some kind of user interface (but which no-one really wants to touch).

Instead of going down that route, incorporating C/C++ into a higher level language often results in a more modular design, less code, better flexibility, and increased programmer productivity.less

SWIG tries to make the problem of C/C++ integration as painless as possible. This allows you to focus on the underlying C program and using the high-level language interface, but not the tedious and complex chore of making the two languages talk to each other. At the same time, SWIG recognizes that all applications are different. Therefore, it provides a wide variety of customization features that let you change almost every aspect of the language bindings. This is the main reason why SWIG has such a large user manual ;-).

如上一節所述,SWIG 的主要目的是簡化 C/C++ 與其餘編程語言集成的任務。可是,爲何有人想這樣作呢?要回答這個問題,列出一些 C/C++ 編程的優勢頗有用:

  • 對編寫程序庫的出色支持。
  • 高性能(數值運算、數據處理、圖形等)。
  • 系統編程和系統集成。
  • 龐大的用戶社區和軟件基礎。

接着,列出一些 C/C++ 編程的問題

  • 編寫用戶界面至關痛苦(即考慮使用 MFC、X十一、GTK 或其餘庫進行編程)。
  • 測試耗時(編譯/調試周期)。
  • 不從新編譯就不容易從新配置或自定義。
  • 模塊化可能很棘手。
  • 安全問題(例如緩衝區溢出)。

爲了解決這些限制,許多程序員得出的結論是,在不一樣的任務使用不一樣的編程語言要容易得多。例如,在 Python 或 Tcl 等腳本語言中編寫圖形用戶界面可能要容易得多(若是須要更多證據,請考慮數百萬程序員使用 Visual Basic 等語言的緣由)。交互式解釋器也能夠做爲有用的調試和測試工具。像 Java 這樣的其餘語言能夠大大簡化編寫分佈式計算軟件的任務。關鍵是不一樣的編程語言提供不一樣的優勢和缺點。並且,任何程序都不太多是完美的。所以,經過將語言組合在一塊兒,你能夠利用每種語言的最佳功能,並大大簡化軟件開發的某些方面。

從 C/C++ 的角度來看,不少人都使用 SWIG,由於他們想要打破傳統的單片機 C 編程模型,那一般會產生相似於下面的程序:

  • 一組有用的函數和變量。
  • 一個啓動全部內容的 main() 程序。
  • 一個可怕的黑客集合,造成了某種用戶界面(但沒有人真正想要碰一碰)。

將 C/C++ 結合到更高級的語言中,一般會致使更加模塊化的設計、更少的代碼、更好的靈活性,以及更高的程序員生產力,而不是沿着老路走下去。

SWIG 試圖使 C/C++ 集成問題儘量輕鬆。這使你能夠專一於底層的 C 程序,並使用高級語言接口,而不是讓兩種語言相互交流的繁瑣複雜的工做。同時,SWIG 認識到全部應用程序都是不一樣的。所以,它提供了各類自定義功能,使你能夠更改語言綁定的幾乎每一個方面。這是 SWIG 擁有如此厚的用戶手冊的主要緣由 ;-)。

2.3 一個 SWIG 示例

The best way to illustrate SWIG is with a simple example. Consider the following C code:

闡釋 SWIG 的最佳方式是一個簡單的例子。考慮如下 C 代碼:

/* File : example.c */

double  My_variable  = 3.0;

/* Compute factorial of n */
int fact(int n) {
  if (n <= 1)
    return 1;
  else
    return n*fact(n-1);
}

/* Compute n mod m */
int my_mod(int n, int m) {
  return(n % m);
}

Suppose that you wanted to access these functions and the global variable My_variable from Tcl. You start by making a SWIG interface file as shown below (by convention, these files carry a .i suffix) :

假設你想要從 Tcl 訪問這些函數和全局變量 My_variable。首先製做一個 SWIG 接口文件,以下所示(按照慣例,這些文件帶有 .i 後綴):

2.3.1 SWIG 接口文件

/* File : example.i */
%module example
%{
/* Put headers and other declarations here */
extern double My_variable;
extern int    fact(int);
extern int    my_mod(int n, int m);
%}

extern double My_variable;
extern int    fact(int);
extern int    my_mod(int n, int m);

The interface file contains ANSI C function prototypes and variable declarations. The %module directive defines the name of the module that will be created by SWIG. The %{ %} block provides a location for inserting additional code, such as C header files or additional C declarations, into the generated C wrapper code.

接口文件包含 ANSI C 函數原型和變量聲明。%module 指令定義 SWIG 建立的模塊的名稱。%{ %} 塊提供了一個位置,用於在生成的 C 包裝器代碼中插入其餘代碼,例如 C 頭文件或其餘 C 聲明。

2.3.2 swig 命令

SWIG is invoked using the swig command. We can use this to build a Tcl module (under Linux) as follows :

使用 swig 命令調用 SWIG。咱們可使用它來構建一個 Tcl 模塊(在 Linux 下),以下所示:

unix > swig -tcl example.i
unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include
unix > gcc -shared example.o example_wrap.o -o example.so
unix > tclsh
% load ./example.so
% fact 4
24
% my_mod 23 7
2
% expr $My_variable + 4.5
7.5
%

The swig command produced a new file called example_wrap.cthat should be compiled along with the example.c file. Most operating systems and scripting languages now support dynamic loading of modules. In our example, our Tcl module has been compiled into a shared library that can be loaded into Tcl. When loaded, Tcl can now access the functions and variables declared in the SWIG interface. A look at the file example_wrap.c reveals a hideous mess. However, you almost never need to worry about it.

swig 命令生成了一個名爲 example_wrap.c 的新文件,該文件應與 example.c 文件一塊兒編譯。如今,大多數操做系統和腳本語言都支持動態加載模塊。在咱們的示例中,咱們的 Tcl 模塊已編譯爲能夠加載到 Tcl 的共享庫。加載後,Tcl 如今能夠訪問 SWIG 接口中聲明的函數和變量。看看文件 example_wrap.c 就會發現可怕的混亂。可是,你幾乎不須要擔憂它。

2.3.3 構建 Perl5 模塊

Now, let's turn these functions into a Perl5 module. Without making any changes type the following (shown for Solaris):

如今,讓咱們將這些函數轉換爲 Perl5 模塊。在不進行任何更改的狀況下鍵入如下內容(針對 Solary 顯示):

unix > swig -perl5 example.i
unix > gcc -c example.c example_wrap.c \
        -I/usr/local/lib/perl5/sun4-solaris/5.003/CORE
unix > ld -G example.o example_wrap.o -o example.so # This is for Solaris
unix > perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23, 7), "\n";
print $example::My_variable + 4.5, "\n";
<ctrl-d>
24
2
7.5
unix >

2.3.4 構建 Python 模塊

Finally, let's build a module for Python (shown for Irix).

最後,讓咱們爲 Python 構建一個模塊(針對 Irix 顯示)。

unix > swig -python example.i
unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0
unix > gcc -shared example.o example_wrap.o -o _example.so
unix > python
Python 2.0 (#6, Feb 21 2001, 13:29:45)
[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> import example
>>> example.fact(4)
24
>>> example.my_mod(23, 7)
2
>>> example.cvar.My_variable + 4.5
7.5

2.3.5 快捷方式

To the truly lazy programmer, one may wonder why we needed the extra interface file at all. As it turns out, you can often do without it. For example, you could also build a Perl5 module by just running SWIG on the C header file and specifying a module name as follows

對於真正懶惰的程序員,人們可能想知道爲何咱們須要額外的接口文件。事實證實,你常常能夠不須要它。例如,你還能夠經過在 C 頭文件上運行 SWIG,並指定模塊名稱來構建 Perl5 模塊,以下所示

unix > swig -perl5 -module example example.h
unix > gcc -c example.c example_wrap.c \
        -I/usr/local/lib/perl5/sun4-solaris/5.003/CORE
unix > ld -G example.o example_wrap.o -o example.so
unix > perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23, 7), "\n";
print $example::My_variable + 4.5, "\n";
<ctrl-d>
24
2
7.5

2.4 支持的 C/C++ 語言特性

A primary goal of the SWIG project is to make the language binding process extremely easy. Although a few simple examples have been shown, SWIG is quite capable in supporting most of C++. Some of the major features include:

  • Full C99 preprocessing.
  • All ANSI C and C++ datatypes.
  • Functions, variables, and constants.
  • Classes.
  • Single and multiple inheritance.
  • Overloaded functions and methods.
  • Overloaded operators.
  • C++ templates (including member templates, specialization, and partial specialization).
  • Namespaces.
  • Variable length arguments.
  • C++ smart pointers.

Most of C++11 is also supported. Details are in the C++11 section.

It is important to stress that SWIG is not a simplistic C++ lexing tool like several apparently similar wrapper generation tools. SWIG not only parses C++, it implements the full C++ type system and it is able to understand C++ semantics. SWIG generates its wrappers with full knowledge of this information. As a result, you will find SWIG to be just as capable of dealing with nasty corner cases as it is in wrapping simple C++ code. In fact, SWIG is able to handle C++ code that stresses the very limits of many C++ compilers.

SWIG 項目的主要目標是使語言綁定過程變得很是容易。雖然只展現了一些簡單的例子,但 SWIG 可以很好地支持 C++ 的大多數功能。主要包括:

  • 完整的 C99 預處理;
  • 所有 ANSI C&C++ 數據類型;
  • 函數、變量與常量;
  • 類;
  • 單繼承與多繼承;
  • 重載函數與方法;
  • 重載運算符;
  • C++ 模板(包括成員模板、特化和偏特化);
  • 命名空間;
  • 變長參數;
  • C++ 智能指針。

支持絕大部分 C++11 功能。細節請見 C++11 章節。

須要着重強調一點,SWIG 不是一個簡單的 C++ 詞法分析工具,就像幾個明顯類似的包裝器生成工具同樣。SWIG 不只解析 C++,它實現了完整的 C++ 類型系統,而且可以理解 C++ 語義。SWIG 在充分了解這些信息的狀況下生成包裝器。所以,你會發現 SWIG 可以像處理簡單的 C++ 代碼同樣處理使人討厭的特殊狀況。事實上,SWIG 可以處理強調許多挑戰 C++ 編譯器極限的代碼。

2.5 非直覺的接口構建

When used as intended, SWIG requires minimal (if any) modification to existing C or C++ code. This makes SWIG extremely easy to use with existing packages and promotes software reuse and modularity. By making the C/C++ code independent of the high level interface, you can change the interface and reuse the code in other applications. It is also possible to support different types of interfaces depending on the application.

當按預期使用時,SWIG 要求對現有 C 或 C++ 代碼進行最少(若是有)修改。這使 SWIG 很是易於使用現有軟件包,並有助於軟件重用和模塊化。經過使 C/C++ 代碼獨立於高級接口,你能夠更改接口,並在其餘應用程序中重用代碼。還能夠根據應用程序支持不一樣類型的接口。

2.6 將 SWIG 整合進構建系統

SWIG is a command line tool and as such can be incorporated into any build system that supports invoking external tools/compilers. SWIG is most commonly invoked from within a Makefile, but is also known to be invoked from popular IDEs such as Microsoft Visual Studio.

If you are using the GNU Autotools (Autoconf/ Automake/ Libtool) to configure SWIG use in your project, the SWIG Autoconf macros can be used. The primary macro is ax_pkg_swig, seehttp://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html#ax_pkg_swig. The ax_python_develmacro is also helpful for generating Python extensions. See theAutoconf Archive for further information on this and other Autoconf macros.

There is growing support for SWIG in some build tools, for example CMake is a cross-platform, open-source build manager with built in support for SWIG. CMake can detect the SWIG executable and many of the target language libraries for linking against. CMake knows how to build shared libraries and loadable modules on many different operating systems. This allows easy cross platform SWIG development. It can also generate the custom commands necessary for driving SWIG from IDEs and makefiles. All of this can be done from a single cross platform input file. The following example is a CMake input file for creating a python wrapper for the SWIG interface file, example.i:

SWIG 是一個命令行工具,所以能夠合併到任何支持調用外部工具/編譯器的構建系統中。SWIG 最常在 Makefile 中調用,但也能夠從流行的 IDE(如 Microsoft Visual Studio)調用。

若是你正在使用 GNU 自動工具(Autoconf/ Automake/ Libtool)來爲你的項目配置 SWIG,可使用 SWIG 的 Autoconf 宏。主要的宏是 ax_pkg_swig,詳見 http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html#ax_pkg_swig。在構建 Python 擴展時 ax_python_devel 也頗有用。細節信息和其餘 Autoconf 宏詳見 Autoconf Archive

一些構建工具中對 SWIG 的支持愈來愈多,例如 CMake 是一個跨平臺的開源構建管理器,內置了對 SWIG 的支持。CMake 能夠檢測 SWIG 可執行文件和許多目標語言庫以進行連接。CMake 知道如何在許多不一樣的操做系統上構建共享庫和可加載模塊。這樣能夠輕鬆實現跨平臺 SWIG 開發。它還能夠生成從 IDE 和 makefile 驅動 SWIG 所需的自定義命令。全部這些均可以從單個跨平臺輸入文件中完成。如下示例是一個 CMake 輸入文件,用於爲 SWIG 接口文件 example.i 建立 python 包裝器:

# This is a CMake example for Python

FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})

FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(example python example.i example.cxx)
SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})

The above example will generate native build files such as makefiles, nmake files and Visual Studio projects which will invoke SWIG and compile the generated C++ files into _example.so (UNIX) or _example.pyd (Windows). For other target languages on Windows a dll, instead of a .pyd file, is usually generated.

上面的示例將生成本機構建文件,例如 makefile、nmake 文件和 Visual Studio 項目文件,它們將調用 SWIG 並將生成的 C++ 文件編譯爲 _example.so(UNIX)或 _example.pyd(Windows)。 對於 Windows 上的其餘目標語言,一般會生成 dll 而不是 .pyd 文件。

2.7 自動化代碼生成

SWIG is designed to produce working code that needs no hand-modification (in fact, if you look at the output, you probably won't want to modify it). You should think of your target language interface being defined entirely by the input to SWIG, not the resulting output file. While this approach may limit flexibility for hard-core hackers, it allows others to forget about the low-level implementation details.

SWIG 旨在生成無需手動修改的工做代碼(事實上,若是查看輸出,你可能不但願對其進行修改)。你應該認爲目標語言接口徹底由 SWIG 的輸入定義,而不是生成的輸出文件。雖然這種方法可能會限制硬核黑客的靈活性,但它容許其餘人忘記低級的實現細節。

2.8 SWIG 與自由

No, this isn't a special section on the sorry state of world politics. However, it may be useful to know that SWIG was written with a certain "philosophy" about programming---namely that programmers are smart and that tools should just stay out of their way. Because of that, you will find that SWIG is extremely permissive in what it lets you get away with. In fact, you can use SWIG to go well beyond "shooting yourself in the foot" if dangerous programming is your goal. On the other hand, this kind of freedom may be exactly what is needed to work with complicated and unusual C/C++ applications.

Ironically, the freedom that SWIG provides is countered by an extremely conservative approach to code generation. At its core, SWIG tries to distill even the most advanced C++ code down to a small well-defined set of interface building techniques based on ANSI C programming. Because of this, you will find that SWIG interfaces can be easily compiled by virtually every C/C++ compiler and that they can be used on any platform. Again, this is an important part of staying out of the programmer's way----the last thing any developer wants to do is to spend their time debugging the output of a tool that relies on non-portable or unreliable programming features. Dependencies are often a source of incompatibilities and problems and so additional third party libraries are not used in the generated code. SWIG will also generally avoid generating code that introduces a dependency on the C++ Standard Template Library (STL). SWIG will generate code that depends on the C libraries though.

這不是關於世界政治糟糕情況的特別章節。然而,知道 SWIG 是由編程的某種「哲學」編寫的,這多是有用的——即程序員是聰明的,工具不該該擋路。所以,你會發現 SWIG 極度地聽任你。事實上,若是危險的編程是你的目標,那麼你可使用 SWIG 遠離「打到本身的腳」。另外一方面,這種自由可能正是處理複雜和不尋常的 C/C++ 應用程序所須要的。

具備諷刺意味的是,SWIG 提供的自由被極端保守的代碼生成方法所抵消。從本質上講,SWIG 是試圖將最高級的 C++ 代碼提煉爲基於 ANSI C 編程的一組定義明確的接口構建技術。所以,你會發現幾乎每一個 C/C++ 編譯器均可以輕鬆編譯 SWIG 接口,而且能夠在任何平臺上使用它們。再一次,這對程序員很重要——任何開發人員最不想要作的一件事就是花時間調試依賴於非便攜或不可靠編程工具的輸出。依賴性一般是不兼容性和問題的根源,所以生成的代碼中不使用其餘第三方庫。SWIG 一般還會避免生成依賴於 C++ 標準模板庫(STL)的代碼。然而,SWIG 將生成依賴於 C 庫的代碼。

後續章節

《3. Windows 上使用 SWIG》

相關文章
相關標籤/搜索