八、SWIG 之 简单案例总结
/* example.i */ %module example %include "example.h" %include "cpointer.i" %include "carrays.i" %include "cmalloc.i" %include "cdata.i" %inline %{ typedef unsigned char GM_UINT8; typedef unsigned int GM_UINT32; %} %inline %{ extern GM_UINT32 variable; extern void print_array(GM_UINT32 x[10]); %} %{ void test_function(); %} %pointer_functions(GM_UINT32, GM_UINT32_p) %array_functions(GM_UINT8, GM_UINT8_Array); extern void add(GM_UINT32 x, GM_UINT32 y, GM_UINT32 *result);
%module + 文件名: 用于生成的 python 文件的文件名
/* example.i */ %module expample // swig -pythopn example.i 之后就会生成 example.py文件, 这个文件是脚本调用C的一个接口文件。脚本文件调用 example.py, 这个文件封装了 C 的接口,、
会帮助我们调用 example.pyd 文件,example.pyd 文件的内容就是 C 语言生成的给 Python 使用的 dll(windows上是pyd)文件。
include + 文件名: 用于引入其他的 .h 文件。
不同的是:
%{ #include }% #include引入的是自己写的 .h 场景较多, #include确保生成的C/C++代码包含该标头。会直接映射到SWIG的头文件中,作用和C/C++中类似;
%include相比之下,%include是一个SWIG指令, 一般用于引入SWIG 内置的 .h 较多。它告诉SWIG在继续之前处理该头文件.这样,SWIG将了解(并生成包装)该头文件中声明的类型和函数。换句话说, %include既引入了头文件的功能,还会让 SWIG 处理其内部的一些函数和操作。如cdata.i 中 cdata、memove函数等。
三、
%{
...
%}%{ ... %} : ...这部分里面的内容由SWIG生成的文件中一字不差被使用,以便生成的文件将被编译,通常放置任何包含和定义等,以便生成的文件进行编译。 也就是 SWIG 会将 ... 直接复制到 SWIG 的接口文件中。差不多就类似于将内部的一些申明直接映射复制到接口文件中。接口文件的函数声明也直接复制过去进行函数声明,但是没有函数实现的部分。
%inline指令将所有跟随文字的代码插入到接口文件的标题部分中.然后由SWIG预处理器和解析器解析代码.
所以它%inline %{ ... %}做了两件事:它将声明放在生成的包装器文件中,它使SWIG生成包装器代码,以便可以从目标语言(Python,Lua,无论如何)调用块中的函数等.情况并非如此%{ ... }%:此类块中的代码不会被包装,只是在生成的包装器文件中逐字转储。可以这样理解, %inline 既实现了 %{...%}的功能,同时也有对函数进行实现的操作实现。同时内联代码块内也可以自定义一些函数功能。
SWIG 的全局变量以及全局函数有点类似于直接产生 SWIG 玩不的接口实现,没有声明这一步,所以在某种层面上可以理解: 全局变量 + %{ ... %} == %inline。 但是全局变量想要直接声明必须先定义,所以全局变量一定要在 %inline 中定义才能使用。 函数的话可以直接定义并能够调用
/* example.h */ typedef unsigned int GM_UINT32; typedef struct Vector { GM_UINT32 x, y, z; } Vector;/* example.c */ #include<stdio.h> #include<string.h> typedef unsigned char GM_UINT8; typedef unsigned int GM_UINT32; GM_UINT32 variable = 10; void add_function(GM_UINT32 x, GM_UINT32 y, GM_UINT32 *result) { *result = x + y; } void print_array(GM_UINT32 x[10]) { int i; for (i = 0; i < 10; i++) { printf("[%d] = %d\n", i, x[i]); } } void test_function() { printf("variable = %d\n", variable); }# script.py import example print(example.cvar.variable) # 10 c = example.new_GM_UINT32_p() example.add_function(3, 4, c) print(example.GM_UINT32_p_value(c)) # 7 example.delete_GM_UINT32_p(c) _data = [1, 2, 3, 4, 5, 6, 7, 8] array = example.new_GM_UINT8_Array(10) [example.GM_UINT8_Array_setitem(array, i, _data[i]) for i in range(len(_data))] b = example.cdata(array, 10) # 从缓存中取值 print((b,)) # ('\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00',) c = example.new_GM_UINT8_Array(100) example.memmove(c, b) print(example.GM_UINT8_Array_getitem(c, 1)) # 2