Swig文件说明

常用字段说明

不同语言之间转换最主要的就是不同语言之间语法的封装,swig就是用来干这些事情的。而这些字段正是指导swig来完成这些操作的指令

/* File : example.i */
%module example
%{/* Put headers and other declarations here */
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
%}
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);

module:指定swig会创建的模块

%module mymodule
%{// 这里是源代码中需要的
#include "myheader.h"
%}
// 这里是转换之后目标代码中需要的
// Now list ISO C/C++ declarations
int foo;
int bar(int x);
...

%{…%}

  • 所有在%{…%}之间的内容会被一字不差的放置到被swig创建的封装的文件中。这个区域通常用来放置一些swig不会生成的定义或者声明,对应C/C++的封装通常用来引入头文件

%+指令

  • 大多数的swig指令都是这种以%开头的指令,目的就是为了能和C能够很好的区分开来

  • 默认情况下,swig是不会对include进来的头文件中的#include进行展开的,除非你指定-includeall

%{/* Include in the generated wrapper file */
typedef unsigned int size_t;
%}
/* Tell SWIG about it */
typedef unsigned int size_t;

Or

%inline %{typedef unsigned int size_t;
%}

像C语言一样,swig中也能使用swig进行类型重定义

%include 引入头文件

使用%include指令来引入swig定义的头文件

%import引入头文件

如果只是想引入文件使用文件中的宏定义和类型可以使用import

%import "foo.i"

预定义变量

为了区分不同语言以及在部分指导文件中能够区别进行,siwg中提前预定义了一些变量

SWIG Always defined when SWIG is processing a file
SWIGIMPORTED Defined when SWIG is importing a file with %import
SWIG_VERSION Hexadecimal (binary-coded decimal) number containing SWIG version,
such as 0x010311 (corresponding to SWIG-1.3.11).
SWIGCSHARP Defined when using C#
SWIGD Defined when using D
SWIGGO Defined when using Go
SWIGGUILE Defined when using Guile
SWIGJAVA Defined when using Java
SWIGJAVASCRIPT Defined when using Javascript
SWIG_JAVASCRIPT_JSC Defined when using Javascript with -jsc
SWIG_JAVASCRIPT_V8 Defined when using Javascript with -v8 or -node
SWIGLUA Defined when using Lua
SWIGMZSCHEME Defined when using Mzscheme
SWIGOCAML Defined when using OCaml
SWIGOCTAVE Defined when using Octave
SWIGPERL Defined when using Perl
SWIGPHP Defined when using PHP (any version)
SWIGPHP7 Defined when using PHP7
SWIGPYTHON Defined when using Python
SWIGR Defined when using R
SWIGRUBY Defined when using Ruby
SWIGSCILAB Defined when using Scilab
SWIGTCL Defined when using Tcl
SWIGXML Defined when using XML__LINE__ Current line number
__FILE__ Current file name
__STDC__ Defined to indicate ISO C
__cplusplus Defined when -c++ option usedSWIG_D_VERSION Unsigned integer target version when using D
SWIGGO_CGO Defined when using Go for cgo
SWIGGO_GCCGO Defined when using Go for gccgo
SWIGGO_INTGO_SIZE Size of the Go type int when using Go (32 or 64)
SWIGPYTHON_PY3 Defined when using Python with -py3
SWIGPYTHON_BUILTIN Defined when using Python with -builtin
SWIG_RUBY_AUTORENAME Defined when using Ruby with -autorename

增强型的宏定义

为了更好的实现对源码的封装,swig提供了一种增强型的宏定义指令, %define 和 %enddef

%define ARRAYHELPER(type, name)
%inline %{type *new_ ## name (int nitems) {return (type *) malloc(sizeof(type)*nitems);
}
void delete_ ## name(type *t) {free(t);
}
type name ## _get(type *t, int index) {return t[index];
}
void name ## _set(type *t, int index, type val) {t[index] = val;
}
%}
%enddef
ARRAYHELPER(int, IntArray)
ARRAYHELPER(double, DoubleArray)

指令透传

正常情况下,在需要封装的函数中,swig会将#define进行处理,如果想让对应的宏定义不进行预处理可以在#前面添加%来实现

%extend Foo {void bar() {%#ifdef DEBUGprintf("I'm in bar\n");%#endif
}
}

指针处理(cpointer.i)

在一些函数中需要传入指针,但是在其他函数中可能没有指针这个概念,因此swig特意为指针提供了封装方式%pointer_functions(int**, intp);的含义就是,提供一个函数封装,这个函数封装可以创建指针执行的内容,这里的含义就是申请一块int大小的内存并返回

%include "cpointer.i"
/* Create some functions for working with "int *" */
%pointer_functions(int, intp);
/* A function that uses an "int *" */
void add(int x, int y, int *result);

如果想处理复杂的或者自定义的class可以使用%pointer_class(int, intp);来进行处理,相比之下使用pointer_class将申请的内容当成一个对象来管理更加的便捷和方便垃圾回收

%module example
%include "cpointer.i"
/* Wrap a class interface around an "int *" */
%pointer_class(int, intp);
/* A function that uses an "int *" */
void add(int x, int y, int *result);

类型转换

当一些类型需要转换是可以使用类型转换指令pointer_cast,第一个参数是当前类型,第二个参数是转换之后的参数,第三个是封装的函数名字

%include "cpointer.i"
%pointer_cast(int *, unsigned int *, int_to_uint);

数组(carrays.i)

使用前先引入头文件,指令方式%array_functions(type, name)

%include "carrays.i"
%array_functions(double, doubleArray);
void print_array(double x[10]);

同样,这里可以使用array_class来封装自定义类型的数组

%module example
%include "carrays.i"
%array_class(double, doubleArray);
void print_array(double x[10]);

内存管理(cmalloc.i)

swig提供了内存管理的模块,使用这些指令可以对malloc,calloc,realloc和free进行封装,具体的指令形式如下

%malloc(type [, name=type])
%calloc(type [, name=type])
%realloc(type [, name=type])
%free(type [, name=type])
%sizeof(type [, name=type])
%allocators(type [, name=type])
// SWIG interface
%include "cmalloc.i"
%malloc(int);
%free(int);
%malloc(int *, intp);
%free(int *, intp);
%allocators(double);

C类型数据封装(cdata.i)

引入cdata.i模块后,会在封装代码中提供Cdata*, memmove()等函数的封装用于申请和释放C类型数据。

如果类型已知可以使用以下方式

%include "carrays.i"
%include "cdata.i"
%array_class(int, intArray);

如果类型是未知类型,就需要借助cdata指令了%cdata(type [, name=type])

内存释放

当一个C中的函数申请一块内存,并返回一个char *类型时,swig可能会判断不出对应的内容是否需要释放,新版本的swig已经能够对简单的源码进行自行判断,如果源码中是申请了一块内存但是没有释放,在目标代码中swig会默认封装上释放的函数,比如go中没有char * 类型的数据,在进行封装时swig会创建一个string类型数据,并将原有的char *内容赋值到string对象中,然后根据判断自动释放对象,但是函数复杂时就需要进行人为指定了,这时需要用到指令%newobject来进行指定

%newobject foo;
char *foo() {char *result = (char *) malloc(sizeof(char));return result;
}

STL的支持

对于STL的支持是一个循序渐进的过程,目前已经支持的STL如下所示

使用STL时需要注意异常的抛出,通常在使用时需要对可能发生的异常进行适当的封装

%module example
%include "std_vector.i"
%typemap(throws) std::out_of_range {// custom exception handler
}
%template(VectInt) std::vector<int>;

更加通用的方法是对所有异常进行封装

%include "exception.i"
%exception {try {$action} catch (const std::exception& e) {SWIG_exception(SWIG_RuntimeError, e.what());}
}

SWIG_exception(int code, const char *message)用于在封装的目标函数代码中抛出异常,常见的错误类型如下

SWIG_MemoryError
SWIG_IOError
SWIG_RuntimeError
SWIG_IndexError
SWIG_TypeError
SWIG_DivisionByZero
SWIG_OverflowError
SWIG_SyntaxError
SWIG_ValueError
SWIG_SystemError

参数类型(typemaps.i)

假如有以下函数,如果不对result进行声明,那么swig只会对按照指针的形式处理result参数,如果你直接传入一个空的result底层会在赋值时直接崩溃

void add(double a, double b, double *result) {*result = a + b;
}

因此需要使用%apply指令来对参数进行指导,对参数添加上指令%apply double *OUTPUT之后,swig已经知道result是一个需要输出的参数,因此会对result的合法性进行检测,如果是异常值(null)那么直接抛出异常

%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{extern void add(double a, double b, double *result);
extern void Sum(double a, double b, double *result);
%}

如果有多个参数需要输出,只需要按照列表的形式向后添加即可

%include "typemaps.i"
%apply int *OUTPUT { int *width, int *height };
// Returns a pair (width, height)
void getwinsize(int winid, int *width, int *height);

如果你嫌每次都要写一长串的指令比较麻烦可以将以上过程简化成如下方式,直接将对应的参数更换成OUTPUT即可

%include "typemaps.i"%inline %{extern void add(double a, double b, double *OUTPUT);
%}

另外需要注意的是,一旦使用%apply进行声明,那么后续所有的double *result参数都会被处理,如果想取消%apply的作用需要进行如下声明:

%clear double *result; // Remove all typemaps for double *result

我们更常用的形式是:

入参

int *INPUT
short *INPUT
long *INPUT
unsigned int *INPUT
unsigned short *INPUT
unsigned long *INPUT
double *INPUT
float *INPUT

出参

int *OUTPUT
short *OUTPUT
long *OUTPUT
unsigned int *OUTPUT
unsigned short *OUTPUT
unsigned long *OUTPUT
double *OUTPUT
float *OUTPUT

即是入参又是出参

int *INOUT
short *INOUT
long *INOUT
unsigned int *INOUT
unsigned short *INOUT
unsigned long *INOUT
double *INOUT
float *INOUT

以上书写方式,直接放到参数上,等同使用apply的如下指令形式

// Make double *result an output value
%apply double *OUTPUT { double *result };
// Make Int32 *in an input value
%apply int *INPUT { int32 *in };
// Make long *x inout
%apply long *INOUT {long *x};
...
%clear double *result;
%clear Int32 *in, long *x;

飞书文档
视频课件

swig教程-指令文件《一》相关推荐

  1. SWIG教程-封装指令的使用《二》

    变量属性 使用immutable创建只读字段,使用该字段编辑的变量在对应目标语言中只有对应的GetX接口,无法对值进行修改. 一个变量一旦被标记为immutable之后,只有明确再次指定为mutabl ...

  2. Xamarin Essentials教程打开文件

    Xamarin Essentials教程打开文件 FileSystem类的OpenAppPackageFileAsync()方法可以用来打开App包中特定的文件,其语法形式如下: public sta ...

  3. Python入门教程之文件读写操作知识

    Python是随着人工智能时代的来临而火爆起来的编程语言,入门简单.功能强大,吸引了人们的广泛学习加入.想要学好Python,一定要从基础学起,然后进阶深入学习,今天千锋小编就给大家分享Python培 ...

  4. 飞秋教程:文件断点续传

    飞秋新版本增加了文件断点续传功能,省去了传大文件时因为网络问题中断又得重新开始传的烦恼,节省时间,提高速度,对于已传过的大文件,重新接收时能实现秒传. 默认情况下文件断点续传功能是在文件大于1M时才开 ...

  5. mcldownload文件夹_《我的世界》中国版游戏空间精简教程 多余文件删除方法

    <我的世界>中国版游戏空间精简教程 多余文件删除方法 2017-09-05 16:09:32来源:网易论坛编辑:评论(0) <我的世界>中国版自从更新后很多玩家都反映游戏所需空 ...

  6. 超详细的实现上传文件功能教程,文件上传实现。

    重要声明:本文章仅仅代表了作者个人对此观点的理解和表述.读者请查阅时持自己的意见进行讨论. 本文更新不及时,请到原文地址浏览:<超详细的实现上传文件功能教程,文件上传实现.>. 一.文件上 ...

  7. AutoJs4.1.0实战教程---js文件打包发布成APK文件

    AutoJs4.1.0实战教程---js文件打包发布 首先需要在手机上安装AutojsApp,下载地址:https://wwa.lanzoui.com/imX3Vpchkdc 需要将Js文件打包发布成 ...

  8. YDOOK:Pydub 使用教程 打开文件 各种格式

    YDOOK:Pydub 使用教程 打开文件 各种格式 © YDOOK Jinwei Lin, shiye.work http://www.ydook.com https://orcid.org/000 ...

  9. Linux 指令——文件和用户管理以及用户权限

    Linux 指令--文件和用户管理以及用户权限 方便快捷指令 文件和用户管理 文件管理 文件管理命令 参数 例子 vim指令 用户管理 管理用户指令 参数 例子 用户权限 用户权限命令 ACL用户权限 ...

最新文章

  1. 合并单元格两行_28 HTML5标签学习——table单元格的合并
  2. wpf控件开发基础(1)
  3. boost::posix_time模块实现本地时间和 UTC 之间的转换的测试程序
  4. 专精开发还是转管理?程序员的职业规划选择,没有想象中那么难
  5. 《组合数学》——卡特兰数
  6. ubuntu16.04 + ros-kinetic 配置cartographer
  7. NSString的几种常用方法
  8. Mysql基础知识:创建、查看、修改和删除表
  9. 【clickhouse】clickhouse数据文件目录移动到新目录并建立软连接
  10. python中numpy函数fft_如何在PyTorch中正确使用Numpy的FFT函数?
  11. 使用 Preload/Prefetch 优化
  12. 如何删除Mac OS X上隐藏的文件?
  13. postman websocket_postman的“替代者”postwoman的使用体验—从入门到放弃
  14. 【LED灯屏控制器】国产FPGA之 AG10KSDE176 初探(1)
  15. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write
  16. 计算机基础中通信概预算,通信工程概预算编制系统的设计与实现
  17. 中小企业采用云计算的三大障碍
  18. 基于单片机指纹考勤机仿真系统-毕设资料
  19. 1_ARCGIS DESKTOP和ORACLE建立林业地理信息数据库
  20. 年中总结 | 愿自己更好面对未来 2022/6

热门文章

  1. win10IE浏览器打不开怎么办
  2. C++:实现车轮轨迹(附完整源码)
  3. CSS清除浮动的三种方法【前端开发】
  4. 企业网络安全存在哪些主要问题
  5. ETL工具KETTLE简介
  6. [安卓开发板]迅为IMX6 四核Android开发板
  7. Texmaker中“弹出单独的界面”模式查看生成的PDF文件
  8. Day3 确知信号的类型、频域性质和时域性质
  9. 中学计算机教材教法试题及答案,中学信息技术教材教法模拟试题jn.pdf
  10. 不属于jsp构成元素_JSP 页面中不能包含脚本元素。( )_学小易找答案