当前位置:网站首页>SWIG tutorial "two"
SWIG tutorial "two"
2022-08-10 14:54:00 【Ah cool studio】
变量属性
使用immutableCreate read-only fields,Variables edited using this field have only counterparts in the corresponding target languageGetX接口,无法对值进行修改.
A variable is once marked as immutable之后,Only explicitly re-specified asmutable,Otherwise it is always a read-only variable
The %immutable directive enables read-only mode until it is explicitly disabled using the %mutable directive
// File : interface.i
int a; // Can read/write
%immutable;
int b, c, d; // Read only variables
%mutable;
double x, y; // read/write
Compatibility note: Read-only access used to be controlled by a pair of directives %readonly and %readwrite. Although these directives still work, they generate a warning message.
Simply change the directives to %immutable; and %mutable; to silence the warning. Don't forget the extra semicolon
重命名
Sometimes when converting the corresponding language to the target language,due to different keywords,Variables that work normally in that language may be keywords in the target language,这个时候可以使用rename进行重命名.
// interface.i
// will be in the source languageprint函数重命名为my_printThis will pass in the target languagemy_printto call in the source languageprint
%rename(my_print) print;
extern void print(const char *);
%rename(foo) a_really_long_and_annoying_name;
extern int a_really_long_and_annoying_name;
renameThe scope is from the beginning of the declaration until the end of the file,So if you want that header file to be renamed, you need to ensure that the header file is importedrename之后
%rename(my_print) print;
%rename(foo) a_really_long_and_annoying_name;
%include "header.h"
// It doesn't matter if you add double quotes or not,But when the renamed name isC++的关键字是,Adding double quotes becomes necessary
%rename("foo_short") foo(short);
%rename(foo_long) foo(long);
void foo(int);
void foo(short); // Accessed as foo_short()
void foo(long); // Accessed as foo_long()
Being able to name a single one is usually enough,但swig的功能远不止于此,Batch naming can be done by matching,Such as adding a prefix to all functions
%rename("myprefix_%s") ""; // print -> myprefix_print
Modify all snake case names to camel case names
%rename("%(lowercamelcase)s") ""; // foo_bar -> fooBar; FooBar -> fooBar
Eliminate some characters in the name from being used
%rename("%(strip:[wx])s") ""; // wxHello -> Hello; FooBar -> FooBar
Rename operator overloaded functions
%rename(__add__) Complex::operator+;
If operator overloading is required for friend function or global function overloading, it is renamed as follows
%rename(op_j) ::operator+;
It also supports matching using regular expressions
// Strip the wx prefix from all identifiers except those starting with wxEVT
%rename("%(regex:/wx(?!EVT)(.*)/\\1/)s") ""; // wxSomeWidget -> SomeWidget
// wxEVT_PAINT -> wxEVT_PAINT
// Apply a rule for renaming the enum elements to avoid the common prefixes
// which are redundant in C#/Java
%rename("%(regex:/^([A-Z][a-z]+)+_(.*)/\\2/)s", %$isenumitem) ""; // Colour_Red -> Red
// Remove all "Set/Get" prefixes.
%rename("%(regex:/^(Set|Get)(.*)/\\2/)s") ""; // SetValue -> Value
// GetValue -> Value
Ignore
使用ignore可以指示swigIgnore things that don't need encapsulation
%ignore print; // Ignore all declarations named print
%ignore MYMACRO; // Ignore a macro
...
#define MYMACRO 123
void print(const char *);
You can choose to ignore most symbols,Only a small part of it is encapsulated
Using the techniques described above it is possible to ignore everything in a header and then selectively wrap a few chosen methods or classes. For example, consider a header, myheader.h
which has many classes in it and just the one class called Star is wanted within this header, the following approach could be taken:
%ignore ""; // Ignore everything
// Unignore chosen class 'Star'
%rename("%s") Star;
// As the ignore everything will include the constructor, destructor, methods etc
// in the class, these have to be explicitly unignored too:
%rename("%s") Star::Star;
%rename("%s") Star::~Star;
%rename("%s") Star::shine; // named method
%include "myheader.h"
It can also be ignored by type
%rename($ignore, %$isclass) ""; // Only ignore all classes
%rename("%s") Star; // Unignore 'Star'
%include "myheader.h"
回调函数
Some functions that need to be passed a callback,需要提前声明,The function implemented by the target function cannot be passed in directly
/* Function with a callback */
int binary_op(int a, int b, int (*op)(int, int));
/* Some callback functions */
// Pass in the callback function to be used
%constant int add(int, int);
%constant int sub(int, int);
%constant int mul(int, int);
Once declared as a callback function,Will not be used as a normal function in the target function,If a function is called as a callback function, it also wants to be called as a normal function,It can be declared as follows
/* Function with a callback */
int binary_op(int a, int b, int (*op)(int, int));
/* Some callback functions */
%callback("%s_cb");
int add(int, int);
int sub(int, int);
int mul(int, int);
%nocallback;
Structure and Analysis
Swig 为每个C++The class generates default constructors and parsing functions,If it is not needed, it can be disabled using parameter options or directives
If you don't want SWIG to generate default constructors for your interfaces, you can use the %nodefaultctor directive or the -nodefaultctor command line option. For example:
swig -nodefaultctor example.i
Or
%module foo
...
%nodefaultctor; // Don't create default constructors
... declarations ...
%clearnodefaultctor; // Re-enable default constructors
Or you can be more precise to specify which class does not create a constructor
%nodefaultctor Foo; // No default constructor for Foo
...
struct Foo { // No default constructor generated.
};
struct Bar { // Default constructor generated.
};
虽然,Not creating an analysis function often results in memory leaks,但是swigStill allows you to control not to create the parsing function throughnodefaultdtorSpecifies the type that does not require a parsing function
%nodefaultdtor Foo; // No default/implicit destructor for Foo
...
struct Foo { // No default destructor is generated.
};
struct Bar { // Default destructor generated.
};
Note: There are also the-nodefault option and %nodefault directive, which disable both the default or implicit destructor generation. This could lead to memory leaks across the target
languages, and it is highly recommended you don't use them
限制
虽然siwgCan handle most of themC++语法,但swig并不是完整的C++解析器,There is still a lot of syntax that isswig无法解析的.
Non-conventional type declarations. For example, SWIG does not support declarations such as the following (even though this is legal C):
/* 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));
为C++The class adds member functions
很多CA struct of type cannot bind member functions,But in other functions,For convenienceswig支持为CTyped structures bind additional member functions to aid in the creation and use of structures,这时就要用到%extend指令了
/* file : vector.h */
...
typedef struct Vector {
double x, y, z;
} Vector;
通过extend指令为C++Add a constructor to a type of struct
// file : vector.i
%module mymodule
%{
#include "vector.h"
%}
%include "vector.h" // Just grab original C header file
%extend Vector { // Attach these functions to struct Vector
Vector(double x, double y, double z) {
Vector *v;
v = (Vector *) malloc(sizeof(Vector));
v->x = x;
v->y = y;
v->z = z;
return v;
}
~Vector() {
free($self);
}
double magnitude() {
return sqrt($self->x*$self->x+$self->y*$self->y+$self->z*$self->z);
}
void print() {
printf("Vector [%g, %g, %g]\n", $self->x, $self->y, $self->z);
}
};
但是extend指令只能用于struct上,Cannot be used for passingtypedefafter the type name
typedef struct Integer {
int value;
} Int;
%extend Integer { ... } /* Correct name */
%extend Int { ... } /* Incorrect name */
struct Float {
float value;
};
typedef struct Float FloatValue;
%extend Float { ... } /* Correct name */
%extend FloatValue { ... } /* Incorrect name */
有一种特殊情况除外,那就是当typedefan anonymous class,是可以使用extend的
typedef struct {
double value;
} Double;
%extend Double { ... } /* Okay */
代码注入
swig代码输出格式
swig输出的C/C++The code will be divided into5部分
Begin section.
A placeholder for users to put code at the beginning of the C/C++ wrapper file. This is most often used to define preprocessor macros that are used in later sections.
Runtime code.
This code is internal to SWIG and is used to include type-checking and other support functions that are used by the rest of the module.
Header section.
This is user-defined support code that has been included by the %{ ... %} directive. Usually this consists of header files and other helper functions.
Wrapper code.
These are the wrappers generated automatically by SWIG.
Module initialization.
The function generated by SWIG to initialize the module upon loading.
Code injection instructions
Command injection format:
// 将在sectionPartially injected code,section为begin runtime header wrapper init等字段
%insert("section") "filename"
// Injects the content of the following code segment into the specified segment
%insert("section") %{ ... %}
当然除了使用insert指令,sectionThe name itself is also an instruction,也可以sectionAs an instruction, code injection is performed on the specified code segment
For example, %runtime is used instead of %insert("runtime").
%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 ...
%}
说明:Actually used often%{....%},其实是%header %{...%}的简写
The bare %{ ... %} directive is a shortcut that is the same as %header %{ ... %}
Init Sections are used by some code that needs to be initialized.
辅助函数
In actual use, the function of code injection is often used to write auxiliary functions
%{
/* Create a new vector */
static Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
%}
// Now wrap it
Vector *new_Vector();
In order to simplify the writing of auxiliary code,引入了inline指令,The command is used as follows:
凡是被inline标记的代码段,It is equivalent to the effect of writing it by hand in both the code and the package:
%inline %{
/* Create a new vector */
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
%}
等效于
%{
/* Create a new vector */
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}%
}
/* Create a new vector */
Vector *new_Vector() {
return (Vector *) malloc(sizeof(Vector));
}
但是需要注意的是,inlineOnly valid for functions and variables,Whether references to header files are encapsulated,Still need the original way,在代码块中使用#include 引入头文件,The header files that need to be encapsulated into object code need to be used outside the code block%includeinstruction to informswigThis header file needs to be encapsulated
说明:编译选项-Dmain=oldmainIn fact, it is used in the macro definition replacement process,A high-speed preprocessor willmainReplace it with the symbol after the equals sign
边栏推荐
- 基于 Azuki 系列:NFT估值分析框架“DRIC”
- Appium进行APP自动化测试
- MySQL - storage engine for databases
- 2022年网络安全培训火了,缺口达95%,揭开网络安全岗位神秘面纱
- 2022-08-10 Daily: Swin Transformer author Cao Yue joins Zhiyuan to carry out research on basic vision models
- 中学数学建模书籍及相关的视频等(2022.08.09)
- Websocket realizes real-time change of chart content
- 使用决策树对鸢尾花进行分类
- 强意识 压责任 安全培训筑牢生产屏障
- Lack of comparators, op amps come to the rescue!(Op amp is recorded as a comparator circuit)
猜你喜欢
随机推荐
CSP-J1 CSP-S1 初赛 第1轮(2022.08.09)
[Semantic Segmentation] DeepLab Series
MySQL 原理与优化:Update 优化
【MinIO】Using tools
JS入门到精通完整版
640. 求解方程 : 简单模拟题
缺少比较器,运放来救场!(运放当做比较器电路记录)
每个月工资表在数据库如何存储?求一个设计思路
BFT机器人带你走进智慧生活 ——探索遨博机器人i系列的多种应用
C#实现访问OPC UA服务器
PyTorch multi-machine multi-card training: DDP combat and skills
王学岗————直播推流(软便)03x264集成与camera推流
Alibaba的秒杀系统—千亿级并发设计手册上线了
统信 UOS V20 专业版(1050update2)发布:文件共享、全局搜索等优化
基于inotify实现落盘文件的跨进程实时读写交互
字节终面:CPU 是如何读写内存的?
《论文阅读》PLATO: Pre-trained Dialogue Generation Model with Discrete Latent Variable
awk的简单使用
波士顿房价预测
In the second half of 2012 system architecture designers afternoon paper II