一、SWIG 之 运行SWIG
SWIG 需要一个包含 ANSI C/C++ 声明和特殊 SWIG 指令的文件作为输入。通常,这是一个特殊的 SWIG 接口文件,用特殊的 .i 或 .swg 后缀表示。在某些情况下,SWIG 可以直接用于原始头文件或源文件。
%module mymodule %{ #include "myheader.h" %} // Now list ANSI C/C++ declarations int foo; int bar(int x); ... /* 模块名由特定的 %module 指令提供。 %{...%} 块中的所有内容都只会逐字复制到 SWIG 最终创建的包装器文件中。此部分几乎总是用于包含头文件和其他声明用于生成的包装器代码的编译。重点强调,
因为仅仅在 SWIG 输入文件中包含一个声明,该声明不会自动出现在生成的包装器代码中,因此需要确保在 %{...%} 部分中包含正确的头文件。
应该注意的是,SWIG 不解析或解释包含在 %{...%} 中的文本。SWIG 中的 %{...%} 语法和语义类似于解析器生成工具)输入文件中的声明部分。 *//* SWIG 的大多数操作都是由特殊指令控制的,这些指令总是以 % 开头,以区别于普通的 C 声明。这些指令用于给 SWIG 提供提示或以某种方式更改 SWIG 的解析行为。 由于 SWIG 指令不是合法的 C 语法,因此通常不可能将它们包含在头文件中。但是,SWIG 指令可以使用条件编译包含在 C 头文件中 */ /* header.h --- Some header file */ /* SWIG directives -- only seen if SWIG is running */ #ifdef SWIG %module foo #endif
swig -python example.i
swig -c++ -python example.i
swig -c++ -python -o example_wrap.cpp example.i
swig -c++ -python -outdir pyfiles -o cppfiles/example_wrap.cpp example.i
# 如果目录 cppfiles 和 pyfiles 存在,将生成以下内容: cppfiles/example_wrap.cpp pyfiles/example.py
/* Non-conventional placement of storage specifier (extern) 非常规位置的存储说明符*/ const int extern Number; /* Extra declarator grouping 额外声明符分组 */ Matrix (foo); // A global variable /* Extra declarator grouping in parameters 参数中的额外声明符分组*/ void bar(Spam (Grok)(Doh));
/* 不建议在 C++ 源文件(.c、.cpp 或 .cxx 文件中的代码)上运行 SWIG。通常的方法是给 SWIG 提供头文件以解析 C++ 定义和声明。
主要原因是如果 SWIG 解析范围定义或声明(对于 C++ 源文件来说是正常的),源文件将被忽略,除非先前解析了符号的声明。例如 */ /* bar not wrapped unless foo has been defined and the declaration of bar within foo has already been parsed 除非定义了foo,并且已经解析了foo中的bar声明,否则不会被解包*/ int foo::bar(int) { ... whatever ... }
// C++ 的某些高级功能(如嵌套类)尚未完全支持, 具体可参考第三章内容 // 如果出现解析错误,可以使用条件编译来跳过非法代码, 或者,你可以从接口文件中删除有问题的代码。 #ifndef SWIG ... some bad declarations ... #endif /* SWIG 没有提供完整的 C++ 解析器实现的原因之一是它被设计为使用不完整的规范,并且在处理 C/C++ 数据类型时非常宽松(例如,即使有丢失的类声明或透明数据类型,SWIG 也可以生成接口)。
不幸的是,这种方法使得实现 C/C++ 解析器的某些部分变得极其困难,因为大多数编译器使用类型信息来帮助解析更复杂的声明 */