当前位置:网站首页>SWIG Tutorial "One"

SWIG Tutorial "One"

2022-08-10 14:54:00 Akure Studio

Swig《一》

Instruction file description

The most important conversion between different languages ​​is the encapsulation of syntax between different languages,swigIt's used to do these things.And these fields are the guidanceswiginstructions to accomplish these operations

/* 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:指定swigmodule will be created

%module mymodule
%{
// Here is what is needed in the source code
#include "myheader.h"
%}
// Here is what is needed in the object code after conversion
// Now list ISO C/C++ declarations
int foo;
int bar(int x);
...

%{....%}

  • 所有在%{....%}The content in between will be placed literallyswigin the created package file.This area is usually used to place someswigDefinitions or declarations that will not be generated,对应C/C++The wrapper is usually used to import header files

%+指令

  • 大多数的swigInstructions are like this%开头的指令,The purpose is to reconcileCcan be distinguished well

  • 默认情况下,swig是不会对includein the incoming header file#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中也能使用swigType redefinition

%include 引入头文件

使用%includeinstructions to importswig定义的头文件

%import引入头文件

If you just want to import the file using the macro definitions and types in the file can be usedimport

%import "foo.i"

预定义变量

To differentiate between different languages ​​and to be able to differentiate in some guidance documents,siwgSome variables are predefined in advance

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 used

SWIG_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

Enhanced macro definitions

In order to better realize the encapsulation of the source code,swigProvides an enhanced macro definition directive, %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)

指令透传

正常情况下,in the function that needs to be encapsulated,swig会将#define进行处理,If you want the corresponding macro definition not to be preprocessed, you can do so#前面添加%来实现

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

指针处理(cpointer.i)

A pointer needs to be passed in some functions,But there may not be a concept of pointers in other functions,因此swigDeliberately provide a way to encapsulate pointers%pointer_functions(int**, intp);的含义就是,Provides a function wrapper,This function encapsulates what can be executed by creating a pointer,The meaning here is to apply for a pieceint大小的内存并返回

%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);

If you want to deal with complex or custom onesclass可以使用%pointer_class(int, intp);来进行处理,相比之下使用pointer_classIt is more convenient and convenient for garbage collection to manage the content of the application as an object

%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);

类型转换

When some types need to be converted, type conversion instructions can be usedpointer_cast,The first parameter is the current type,The second parameter is the parameter after conversion,The third is the encapsulated function name

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

数组(carrays.i)

Import header files before use,指令方式%array_functions(type, name)

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

同样,这里可以使用array_classto encapsulate an array of custom types

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

内存管理(cmalloc.i)

swigProvides modules for memory management,Use these commands to correctmalloc,calloc,realloc和free进行封装,The specific command form is as follows

%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);

CType data encapsulation(cdata.i)

引入cdata.i模块后,will be provided in the wrapper codeCdata*, memmove()The encapsulation of other functions is used to apply and releaseC类型数据.

The following methods can be used if the type is known

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

If the type is an unknown type,就需要借助cdata指令了%cdata(type [, name=type])

内存释放

当一个CThe function in allocates a block of memory,并返回一个char *类型时,swigIt may not be possible to determine whether the corresponding content needs to be released,新版本的swigIt has been able to make self-judgment on simple source code,If the source code applies for a piece of memory but does not release it,在目标代码中swigBy default, functions that are freed are encapsulated,比如go中没有char * 类型的数据,在进行封装时swig会创建一个string类型数据,并将原有的char *内容赋值到string对象中,Then the object is automatically released according to the judgment,But when the function is complex, it needs to be specified manually,Commands are required at this time%newobject来进行指定

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

STL的支持

对于STLSupport is a gradual process,目前已经支持的STL如下所示

STL
STL

使用STLBe careful when throwing exceptions,Appropriate encapsulation of possible exceptions is usually required when using them

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

A more general approach is to wrap all exceptions

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

SWIG_exception(int code, const char *message)Used to throw exceptions in the encapsulated target function code,Common error types are as follows

SWIG_MemoryError
SWIG_IOError
SWIG_RuntimeError
SWIG_IndexError
SWIG_TypeError
SWIG_DivisionByZero
SWIG_OverflowError
SWIG_SyntaxError
SWIG_ValueError
SWIG_SystemError

参数类型(typemaps.i)

If there is the following function,如果不对result进行声明,那么swigIt will only be processed in the form of a pointerresult参数,If you pass in an empty one directlyresultThe bottom layer will crash directly on assignment

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

因此需要使用%applycommand to guide the parameters,Add a directive to the parameter%apply double *OUTPUT之后,swig已经知道resultis a parameter that needs to be output,因此会对resultthe legitimacy of the test,If it is an outlier(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);
%}

If there are multiple parameters to output,Just add it backwards in the form of a list

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

If you think it is troublesome to write a long series of instructions every time, you can simplify the above process into the following way,Directly replace the corresponding parameters with OUTPUT即可

%include "typemaps.i"

%inline %{
extern void add(double a, double b, double *OUTPUT);
%}

另外需要注意的是,一旦使用%apply进行声明,那么后续所有的double *resultparameters are processed,如果想取消%applyThe role needs to be declared as follows:

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

Our more commonly used form is :

入参

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

That is, the input and the output

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

the above writing,directly on the parameter,等同使用applyof the following command form

// 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;
原网站

版权声明
本文为[Akure Studio]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/222/202208101431162359.html