一、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 输出

    SWIG 的输出是一个 C/C++ 文件,其中包含构建扩展模块所需的所有包装器代码。SWIG 可能会根据目标语言生成一些其他文件。默认情况下,名为 file.i 的输入文件将转换为文件 file_wrap.c 或 file_wrap.cxx(取决于是否使用了 -c++ 选项)。可以使用 -o 选项更改 C/C++ 输出文件的名称。在某些情况下,编译器使用文件后缀来确定源语言(C、C++ 等)。因此,如果需要不同于默认值的东西,则必须使用 -o 选项来更改 SWIG 生成的包装器文件的后缀。

2.1 C 输出

swig -python example.i

2.2 c++默认输出 cxx.c

swig -c++ -python example.i

2.3 C++修改输出文件名

swig -c++ -python -o example_wrap.cpp example.i

2.4 修改输出文件位置

对于许多目标语言,SWIG 还将生成目标语言的代理类文件。这些特定于语言的文件的默认输出目录与生成的 C/C++ 文件是同一目录。这可以使用 -outdir 选项进行修改。

swig -c++ -python -outdir pyfiles -o cppfiles/example_wrap.cpp example.i
# 如果目录 cppfiles 和 pyfiles 存在,将生成以下内容:

cppfiles/example_wrap.cpp
pyfiles/example.py

三、解析限制

    虽然 SWIG 可以解析大多数 C/C++ 声明,但它不提供完整的 C/C++ 解析器实现。大多数这些限制都与非常复杂的类型声明,以及某些高级 C++ 功能有关。具体而言,目前不支持以下功能:

3.1 非传统类型声明

/* 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));

3.2 不建议在 C/C++ 源文件上运行 SWIG

/*
不建议在 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 ... }

3.3 C++ 的某些高级功能(如嵌套类)尚未完全支持

// C++ 的某些高级功能(如嵌套类)尚未完全支持, 具体可参考第三章内容

// 如果出现解析错误,可以使用条件编译来跳过非法代码, 或者,你可以从接口文件中删除有问题的代码。
#ifndef SWIG
... some bad declarations ...
#endif
    
/*
SWIG 没有提供完整的 C++ 解析器实现的原因之一是它被设计为使用不完整的规范,并且在处理 C/C++ 数据类型时非常宽松(例如,即使有丢失的类声明或透明数据类型,SWIG 也可以生成接口)。
不幸的是,这种方法使得实现 C/C++ 解析器的某些部分变得极其困难,因为大多数编译器使用类型信息来帮助解析更复杂的声明
*/

 

posted on 2022-11-19 12:22  软饭攻城狮  阅读(135)  评论(0编辑  收藏  举报

导航