六、SWIG 之 代码插入
有时需要在 SWIG 生成的结果包装器文件中插入特殊代码。例如,你可能希望包含其他 C 代码以执行初始化或其他操作。插入代码有四种常用方法,但首先了解如何构造 SWIG 的输出很有用。
当 SWIG 创建其输出 C/C++ 文件时,它将分为五个部分,分别对应于运行时代码、头文件、包装器函数和模块初始化代码(按此顺序)。
开始部分 : 用户的占位符,用于将代码放在 C/C++ 包装器文件的开头。这通常用于定义后续部分中使用的预处理器宏。
运行时代码: 此代码是 SWIG 的内部代码,用于包含类型检查和其他模块使用的支持函数。
头文件部分: 这是用户定义的支持代码,已由 %{...%} 指令包含。通常这包括头文件和其他辅助函数。
包装器函数: 这些是 SWIG 自动生成的包装器。
模块初始化: SWIG 生成的函数,用于在加载时初始化模块。
说明: 尚未研究出来,待后续继续研究
%insert 指令允许将代码块插入生成代码的给定部分。它可以使用以下两种方式之一:
%insert("section") "filename" %insert("section") %{ ... %}第一种将把给定 filename 中文件的内容转储到命名的 section 中。第二种将大括号之间的代码插入到命名的 section 中。例如,以下内容将代码添加到运行时部分:
%insert("runtime") %{ ... code in runtime section ... %}有 5 个部分,但是,一些目标语言在附加部分中添加,其中一些导致代码生成到目标语言文件而不是 C/C++ 包装器文件。目标语言章节中提供了这些内容。以代码段命名的宏可用作附加指令,并且通常使用这些宏指令而不是 %insert。例如,使用 %runtime 而不是 %insert("runtime")。生成的 C/C++ 包装器文件中的有效部分和部分的顺序如下所示:
%begin %{ ... code in begin section ... %} %runtime %{ ... code in runtime section ... %} %header %{ ... code in header section ... %} %wrapper %{ ... code in wrapper section ... %} %init %{ ... code in init section ... %}
// example.c typedef struct Vector { int x, y, z; } Vector;/* example.i */ %module example %{ #include "example.h" %} %inline %{ Vector *new_Vector(int x, int y, int z) { Vector *v; v = (Vector *)malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; printf("v->x=%d,v->y=%d,v->z=%d \n", v->x, v->y, v->z); return v; } void delete_Vector(Vector *v) { free(v); } %}%inline 指令将逐字输入的所有代码插入到接口文件的头文件部分中。然后由 SWIG 预处理器和解析器解析代码。因此,上面的示例仅使用一个声明创建一个新命令 new_Vector。由于 %inline%{...%} 块内的代码被赋予 C 编译器和 SWIG,因此在 %{...%} 块中包含任何 SWIG 指令是非法的。
// example.c int init_variables() { int a = 10; return a; }/* example.i */ %module example %{ #include "example.h" %} %init %{ init_variables(); %}# script.py import example vector = example.init_variables() print(vector) # 10