2 SWIG Introduction

1 Preface

1.1 Introduction

  SWIG(简化包装器和接口生成器)是一个软件开发工具,用于为C和c++程序构建脚本语言接口。SWIG最初开发于1995年,最初被洛斯阿拉莫斯国家实验室理论物理部门的科学家用于构建用户界面,以模拟运行在Connection Machine 5超级计算机上的代码。在这种环境下,科学家需要处理大量的模拟数据、复杂的硬件和不断变化的代码库。使用脚本语言接口提供了简单但高度灵活的功能。

  尽管SWIG最初是为科学应用程序开发的,但它已经发展成为一种通用工具,可用于各种各样的应用程序——实际上几乎涉及C/ c++编程的任何应用程序。

1.2 SWIG Versions

  在20世纪90年代后期,SWIG最稳定的版本是1.1p5。版本1.3.X是正式的开发版本,从2000年开始的10年时间里发布了这些版本。最终版本在1.3.X系列是1.3.40,但实际上是1.3.X系列已经稳定了很多年。官方发布了一个稳定版本,同时做出了对SWIG许可证进行更改的决定,这在2010年产生了版本2.0.0。版本3.0.0于2014年发布,主要关注添加c++ 11支持和c++嵌套类。版本4.0.0于2019年发布,添加了Doxygen支持。

1.3 SWIG License

  在顶层目录中,随SWIG一起提供的LICENSE文件包含SWIG许可证。欲进一步了解包括SWIG输出代码许可在内的许可证,请访问SWIG法律页面http://www.swig.org/legal.html。

  许可证在2.0.0版本中得到了澄清,这样SWIG生成的代码可以根据用户的选择/需求在许可证条款下发布,同时SWIG源代码被置于GNU通用公共许可证版本3之下。

1.4 SWIG resources

  SWIG相关材料的官方位置为 http://www.swig.org ,这个站点包含软件的最新版本、用户指南以及关于bug、安装问题和实现技巧的信息。

  您还可以通过访问 http://www.swig.org/mail.html 订阅swig用户邮件列表。

  邮件列表经常讨论SWIG的一些更技术性的方面,以及关于beta版本和未来工作的信息。

  还可以使用Git和Subversion访问最新版本的SWIG。有关这方面的更多资料,请浏览:SWIG Bleeding Edge 。

1.5 Prerequisites

  本手册假设您知道如何编写C/ c++程序,并且至少听说过脚本语言,如Tcl、Python和Perl。不需要详细了解这些脚本语言,但熟悉一些也无妨。不需要有为这些语言构建C扩展的经验——毕竟,这是SWIG自动完成的工作。但是,您应该相当熟悉编译器链接器makefile的使用,因为编写脚本语言扩展比编写普通的C程序要复杂一些。

  随着时间的推移,SWIG发行版的c++处理能力显著提高——尤其是对名称空间、重载操作符和模板等高级特性的支持。只要有可能,本手册将尝试涵盖该接口的技术细节。然而,这并不是一本关于c++编程的教程。对于许多血淋淋的细节,您几乎肯定需要参考好的c++参考资料。如果你不使用c++编程,你可能只想跳过手册中的这些部分。

1.6 Organization of this manual

  本手册的前几章大致描述了SWIG并概述了其功能。其余章节专门介绍特定的SWIG语言模块,并且是自包含的。因此,如果您正在使用SWIG来构建Python接口,那么您可能可以跳到那一章并找到几乎所有您需要知道的内容。

1.7 How to avoid reading the manual

  如果你讨厌阅读手册,看一下“导言”,里面有几个简单的例子。这些示例包含了使用SWIG所需要知道的大约95%的内容。之后,只需使用特定于语言的章节作为参考。SWIG发行版还提供了一个大目录的示例,用于说明不同的主题。

1.8 Backwards compatibility

  如果您以前是SWIG的用户,就不要期望SWIG提供完全的向后兼容性。尽管开发人员尽最大努力保持向后兼容性,但这并不总是可能的,因为随着时间的推移,主要目标是使SWIG变得更好——如果开发人员不断陷入向后兼容性问题,那么这个过程就不可能实现。潜在的不兼容性在详细的发布说明中有明确的标记。

  如果需要使用不同版本的SWIG,并且存在向后兼容性问题,则可以使用SWIG_VERSION预处理器符号,该符号包含正在执行的SWIG的版本。SWIG_VERSION为十六进制整数,如0x010311(对应SWIG-1.3.11)。这可以在接口文件中用于定义不同的类型映射,利用不同的特性等:

#if SWIG_VERSION >= 0x010311
/* Use some fancy new feature */
#endif
注意:在生成的SWIG包装器文件中没有定义版本符号。SWIG预处理器从SWIG-1.3.11开始定义SWIG_VERSION。

1.9 Release notes

  在顶级目录中,随SWIG附带的CHANGES.current、CHANGES和RELEASENOTES文件分别包含当前版本的详细发布说明、以前版本的详细发布说明和swg -1.3.22之后的简要发布说明。

1.10 Credits

  SWIG是一个没有资金支持的项目,如果没有许多在业余时间工作的人的贡献,这是不可能实现的。如果您已经从使用SWIG中受益,请考虑捐赠给SWIG以继续发展。在过去的一段时间里,有很多不同的人在各个层面做出了贡献。在SWIG附带的版权文件或更改文件中或在提交的bug中都会提到贡献者。

1.11 Bug reports

  尽管我们已经尽了一切努力来消除SWIG的bug,但我们也在努力改进可能会引入bug的特性。要报告一个bug,要么向SWIG -devel邮件列表中的SWIG开发人员列表发送邮件,要么在SWIG bug跟踪器中报告一个bug。在您的报告中,要尽可能具体,包括(如果适用)错误消息、回溯(如果发生核心转储)、所使用的SWIG接口文件的相应部分,以及SWIG生成的包装器代码的任何重要部分。我们只有在知道bug的情况下才能修复它们。

2 Introduction

2.1 What is SWIG?

  SWIG是一种软件开发工具,它简化了将不同语言与C和c++程序接口的任务。简而言之,SWIG是一种编译器,它接受C/ c++声明,并创建从其他语言(包括Perl、Python、Tcl、Ruby、Guile和Java)访问这些声明所需的包装器。SWIG通常不需要对现有代码进行修改,通常可以在几分钟内构建一个可用的接口。SWIG可能的应用包括:

  为现有的C程序构建解释接口。

  快速原型和应用程序开发。

  交互程序调整

  将遗留软件重新设计或重构为脚本语言组件。

  制作图形用户界面(例如使用Tk)。

  测试C库和程序(使用脚本)。

  为脚本语言构建高性能C模块。

  使C编程更有趣(或更可容忍,取决于您的观点)。

  • Impressing your friends.
  • Obtaining vast sums of research funding (although obviously not applicable to the author).

  SWIG最初的设计目的是让科学家和工程师非常容易地构建可扩展的科学软件,而不需要获得软件工程学位。因此,SWIG的使用往往是非正式的和特别的(例如,SWIG不像专用IDL编译器那样要求用户提供正式的接口规范)。虽然这种开发风格并不适合每个项目,但它特别适合小型的软件开发;特别是科学研究中常见的研究与开发工作。然而,目前已知SWIG被用于许多大型开源和商业项目。

2.2 Why use SWIG?

  如前一节所述,SWIG的主要目的是简化将C/ c++与其他编程语言集成的任务。然而,为什么会有人想这么做呢?为了回答这个问题,列出一些C/ c++编程的优点是很有用的:

  • 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.

  接下来,让我们列出一些关于C/ c++编程的问题

  • 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).

  为了解决这些限制,许多程序员得出结论,为不同的任务使用不同的编程语言要容易得多。例如,用Python或Tcl这样的脚本语言编写图形用户界面可能要容易得多(如果需要更多的证据,可以考虑一下为什么数百万程序员都使用Visual Basic这样的语言)。交互式解释器也可以作为一个有用的调试和测试工具。Java等其他语言可能会极大地简化编写分布式计算软件的任务。关键是

  从C/ c++的角度来看,很多人使用SWIG是因为他们想要打破传统的单片C编程模型,这通常会导致类似于这样的程序:

  • A collection of functions and variables that do something useful.
  • 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).

  与其走这条路,不如将C/ c++整合到更高级别的语言中,这通常会带来更模块化的设计、更少的代码、更好的灵活性,并提高程序员的生产力。

  SWIG试图使C/ c++集成的问题尽可能轻松。这使您可以专注于底层的C程序和使用高级语言接口,而不是使这两种语言相互通信的繁琐和复杂的工作。同时,SWIG认识到所有应用程序都是不同的。因此,它提供了各种各样的定制特性,让您几乎可以更改语言绑定的每个方面。这是SWIG有这么大的用户手册的主要原因;-)。

2.3 Target languages

  SWIG本质上是一个生成代码的工具,用于使C/ c++代码可用于各种其他编程语言。这些高级编程语言是SWIG代码生成器的目标语言,而C或c++是输入语言。在运行SWIG时,必须指定单一的目标语言。这将导致生成C/ c++和指定的目标语言之间的接口代码。可以多次调用SWIG,但是在每次调用时指定了不同的目标语言。将C/ c++接口到许多不同的目标语言的能力是SWIG的能力之一。

  SWIG主要由两个组件组成。核心组件根据输入ISO C/ c++和SWIG指令(C/ c++标准的扩展)创建解析树。然后,解析树被传递给第二个组件,这是一个目标语言模块,用于生成特定于更高级别语言的代码。SWIG支持许多不同的目标语言。这些目标语言的状态是“支持”或“实验”。提供这种状态是为了表明在使用特定目标语言时所期望的成熟度级别,因为并非所有目标语言都已完全开发。

  SWIG文档的第二部分包含了针对每个目标级别语言的章节。每一章将陈述该语言的状态(支持的或实验的)。

2.3.1 Supported status

  目标语言的状态为“Supported”

  • It is in a mature, well functioning state.
  • It has its own comprehensive chapter in the documentation.
  • It passes all of the main SWIG test-suite and has a range of working examples.
  • It supports the vast majority of SWIG features.
  • It provides strong backwards compatibility between releases.

  以上是一个简短的总结,进一步的细节在扩展章节的支持状态一节中概述。好消息是,所有著名的和最流行的语言都具有这种地位。

2.3.2 Experimental status

  当目标语言处于“实验”状态时

  • It is of sub-standard quality, failing to meet the above 'Supported' status.
  • It is somewhere between the mid to mature stage of development.
  • It does not guarantee any backwards compatibility between releases.
  • It is in need of help to finish development.

  任何使用实验性目标语言的人,如果他们希望使用目标语言模块,强烈建议协助其开发。

  当使用实验目标语言时,SWIG会显示一个警告,以设置期望并强调目标语言的实验状态。如果需要,通常的警告抑制技术可以使用。

  以上是一个简短的总结,进一步的细节将在扩展章节的实验状态部分中概述。

2.4 A SWIG example

  说明SWIG的最好方法是使用一个简单的示例。考虑下面的C代码:

 1 /* File : example.c */
 2 
 3 double My_variable = 3.0;
 4 
 5 /* Compute factorial of n */
 6 int fact(int n) {
 7   if (n <= 1)
 8     return 1;
 9   else
10     return n*fact(n-1);
11 }
12 
13 /* Compute n mod m */
14 int my_mod(int n, int m) {
15   return(n % m);
16 }

  假设您想要访问这些函数和Tcl中的全局变量My_variable。首先创建如下所示的SWIG接口文件(按照惯例,这些文件带有i后缀):

2.4.1 SWIG interface file

 1 /* File : example.i */
 2 %module example
 3 %{
 4 /* Put headers and other declarations here */
 5 extern double My_variable;
 6 extern int    fact(int);
 7 extern int    my_mod(int n, int m);
 8 %}
 9 
10 extern double My_variable;
11 extern int    fact(int);
12 extern int    my_mod(int n, int m);

  接口文件包含ISO C函数原型和变量声明。%module指令定义了将由SWIG创建的模块的名称。%{%}块提供了一个位置,用于在生成的C包装器代码中插入额外的代码,例如C头文件或额外的C声明。

2.4.4 Building a Python module

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

2.5 Supported C/C++ language features

  SWIG项目的一个主要目标是使语言绑定过程极其简单。虽然已经展示了几个简单的示例,但SWIG非常能够支持大多数c++。一些主要的特点包括:

  • Full C99 preprocessing.
  • All ISO 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.

  也支持大部分c++ 11。详细内容见c++ 11章。c++ 14的支持将在c++ 14章节中介绍。c++ 17的支持将在c++ 17章节中介绍。

  需要强调的是,SWIG不像几个明显相似的包装器生成工具那样是一个简单的c++词法分析工具。SWIG不仅解析c++,还实现了完整的c++类型系统,并且能够理解c++语义。SWIG在充分了解这些信息的情况下生成它的包装器。因此,您将发现SWIG处理棘手的拐角情况的能力与它包装简单的c++代码的能力一样。事实上,SWIG能够处理许多c++编译器的极限。

2.6 Non-intrusive interface building

  当按预期使用时,SWIG只需要对现有的C或c++代码进行最小程度的修改(如果有的话)。这使得SWIG非常容易与现有包一起使用,并促进了软件重用和模块化。通过使C/ c++代码独立于高级接口,您可以更改接口并在其他应用程序中重用代码。还可以根据应用程序支持不同类型的接口。

2.7 Incorporating SWIG into a build system

  SWIG是一个命令行工具,因此可以集成到任何支持调用外部工具/编译器的构建系统中。SWIG最常从Makefile中调用,但也可以从流行的ide(如Microsoft Visual Studio)中调用。

  如果您正在使用GNU Autotools (Autoconf/ Automake / Libtool)来配置项目中的SWIG使用,那么可以使用SWIG Autoconf宏。主要的宏是ax_pkg_swig,请参见http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html#ax_pkg_swig。ax_python_devel宏也有助于生成Python扩展。有关这个宏和其他Autoconf宏的更多信息,请参阅Autoconf Archive。

  在一些构建工具中对SWIG的支持越来越多,例如CMake是一个跨平台、开源的构建管理器,内置了对SWIG的支持。CMake可以检测SWIG可执行文件和许多用于链接的目标语言库。CMake知道如何在许多不同的操作系统上构建共享库和可加载模块。这使得跨平台SWIG开发变得容易。它还可以生成从ide和makefile中驱动SWIG所需的自定义命令。所有这些都可以通过一个跨平台输入文件完成。下面的例子是一个CMake输入文件,用于为SWIG接口文件创建Python包装器,example.i

 1 # This is a CMake example for Python
 2 
 3 FIND_PACKAGE(SWIG REQUIRED)
 4 INCLUDE(${SWIG_USE_FILE})
 5 
 6 FIND_PACKAGE(PythonLibs)
 7 INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
 8 
 9 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
10 
11 SET(CMAKE_SWIG_FLAGS "")
12 
13 SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)
14 SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall")
15 SWIG_ADD_MODULE(example python example.i example.cxx)
16 SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})

  上面的示例将生成本机构建文件,如makefiles、nmake文件和Visual Studio项目,这些项目将调用SWIG并将生成的c++文件编译为_example.so (UNIX)或_example.pyd (Windows)。对于Windows上的其他目标语言,通常生成dll文件,而不是.pyd文件。

2.8 Hands off code generation

  SWIG旨在生成不需要手工修改的工作代码(实际上,如果查看输出,您可能不希望修改它)。您应该认为目标语言接口完全由SWIG的输入定义,而不是由结果输出文件定义。虽然这种方法可能会限制硬核黑客的灵活性,但它允许其他人忘记低级实现细节。

2.9 SWIG and freedom

  不,这不是一个关于世界政治可悲状态的专题。然而,知道SWIG是基于某种编程“哲学”编写的可能是有用的——即程序员是聪明的,工具应该远离他们的方式。正因为如此,您会发现SWIG在允许您为所欲为方面非常宽容。事实上,如果危险的编程是您的目标,那么您可以使用SWIG来超越“搬起石头砸自己的脚”。另一方面,这种自由可能正是处理复杂和不寻常的C/ c++应用程序所需要的。具有讽刺意味的是,SWIG提供的自由被一种极其保守的代码生成方法所抵消。在其核心,SWIG试图将最先进的c++代码提炼为基于ISO C编程的小型定义良好的接口构建技术集。因此,您将发现SWIG接口可以被几乎每一个C/ c++编译器轻松地编译,并且可以在任何平台上使用。再者,这是避免程序员干扰的一个重要部分----任何开发人员最不愿意做的事情就是花时间调试一个依赖于不可移植或不可靠编程特性的工具的输出。依赖关系通常是不兼容和问题的来源,因此在生成的代码中不使用额外的第三方库。SWIG通常也会避免生成引入对c++标准模板库(STL)依赖的代码。不过,SWIG将生成依赖于C库的代码。

 

posted @ 2021-11-28 23:18  神龙逗勇士  阅读(70)  评论(0编辑  收藏  举报