SWIG 之三:“11 Typemaps”

原文地址:11 Typemaps

11.1 简介

  typemaps 是SWIG中的一种高级定制功能, 可以直接指定代码包装转换的底层行为。

11.1.1 类型转换

  在SWIG代码包装生成中最重要的问题之一就是不用语言之间的数据类型转换。

11.1.2 typemaps

  使用 %typemap 指令来指示转换代码行为,in表示从目标语言到C/C++,out表示从C/C++到目标语言:

/* Convert from Python --> C */
%typemap(in) int {
  $1 = PyInt_AsLong($input);
}

/* Convert from C --> Python */
%typemap(out) int {
  $result = PyInt_FromLong($1);
}

  扩展了许多以$前缀的特殊变了用来应对复杂语言(如Java)的转换,$input 表示需要转换成C/C++的输入对象,$result 表示包装函数的返回对象,$1表示一个C/C++变量。举个例子:

int gcd(int x,int y);

  对应包装内容可能是这样的:

PyObject *wrap_gcd(PyObject *self, PyObject *args) {
  int arg1;
  int arg2;
  int result;
  PyObject *obj1;
  PyObject *obj2;
  PyObject *resultobj;

  if (!PyArg_ParseTuple("OO:gcd", &obj1, &obj2)) return NULL;

  /* "in" typemap, argument 1 */
  {
    arg1 = PyInt_AsLong(obj1);
  }

  /* "in" typemap, argument 2 */
  {
    arg2 = PyInt_AsLong(obj2);
  }

  result = gcd(arg1, arg2);

  /* "out" typemap, return value */
  {
    resultobj = PyInt_FromLong(result);
  }

  return resultobj;
}

11.1.3 模式匹配

  typemap支持typedef 改名操作。

11.1.4 复用typemaps

  用 %typemap 可以指定某些类型的行为与已知类型行为一致:

%typemap(in) Integer = int;
%typemap(in) (char *buffer, int size) = (char *str, int len);

  其实还可以用 %apply 更简洁:

%typemap(in) int {
  /* Convert an integer argument */
  ...
}
%typemap(out) int {
  /* Return an integer value */
  ...
}

/* Apply all of the integer typemaps to size_t */
%apply int { size_t };    // 花括号里面还可以用逗号分隔多种数据类型的转换,都转成int的行为

  如果已经用 typedef int size_t; 操作指定了改名,就不需要再用上面的指令来转换了。

11.1.5 使用typemaps可以干什么?

  主要作用是用来定义C/C++层包装代码的生成行为。目前可以解决六大类问题:

(1)参数处理

  • %typemap(in)                输入参数转换
  • %typemap(typecheck)  输入参数类型检查重载方法中使用的类型
  • %typemap(argout)        输出参数处理
  • %typemap(check)         输入参数值检查
  • %typemap(arginit)        输入参数初始化
  • %typemap(default)        默认参数
  • %typemap(freearg)       输入参数资源管理

(2)返回值处理

  • %typemap(out)              函数返回值转换
  • %typemap(ret)               返回值资源管理(“ret”类型映射)
  • %typemap(newfree)      新分配对象的资源管理(“newfree”typemap)

(3)异常处理

  • %typemap(throw)          处理C ++异常规范

(4)全局变量

  • %typemap(varin)           分配全局变量
  • %typemap(varout)         读取全局变量

(5)成员变量

  • %typemap(memberin)    将数据分配给类/结构成员

(6)常量定义

  • %typemap(consttab / constcode)     定义常量

11.1.6 使用typemaps 不能干什么?

(1)不能通过函数返回值来区分一个特性,例如:

Foo *make_Foo(int n);

  要想实现这一点可以借助 %feature 来实现。

(2)不能改变参数的调用顺序,例如:

void foo(int, char *);

  要想实现参数的转换可以定义辅助函数:

%rename(foo) wrap_foo;
%inline %{
void wrap_foo(char *s, int x) {
  foo(x, s);
}
%}

11.1.7 与面向对象编程的相似点

11.1.8 本章附录

11.2 Typemap规范

11.2.1 定义typemap

%typemap(method [, modifiers]) typelist code ;
  • method      指定typemap类型,前面括号里的“in”、“out”之类的字符串就是。
  • modifiers   是name="value" 可称作typemap属性,附加一些额外信息,与目标语言有关。可选。
  • typelist       是C++类型模式匹配表。
  • code           是typemap中使用的代码,通常是C/C++代码,也可以是目标语言代码。

  其中 typelist 可以用逗号分隔写多个匹配模式,规则如下:

typelist    :  typepattern [, typepattern, typepattern, ... ] ;

typepattern :  type [ (parms) ]
            |  type name [ (parms) ]
            |  ( typelist ) [ (parms) ]

  而 code 则可以有三种形式可选:

code       : { ... }
           | " ... "
           | %{ ... %}

  来举几个例子:

/* 简单的typemap示例 */
%typemap(in) int {
  $1 = PyInt_AsLong($input);
}
%typemap(in) int "$1 = PyInt_AsLong($input);";
%typemap(in) int %{
  $1 = PyInt_AsLong($input);
%}

/* 带有参数名称的typemap */
%typemap(in) int nonnegative {
  ...
}

/* 支持多种类型的typemap */
%typemap(in) int, short, long {
  $1 = SvIV($input);
}

/* 带有modifiers的typemap */
%typemap(in, doc="integer") int "$1 = scm_to_int($input);";

/* 支持多参数模式的typemap */
%typemap(in) (char *str, int len),
             (char *buffer, int size)
{
  $1 = PyString_AsString($input);
  $2 = PyString_Size($input);
}

/* 带有额外模式参数的typemap */
%typemap(in, numinputs=0) int *output (int temp),
                          long *output (long temp)
{
  $1 = &temp;
}

11.2.2 类型映射范围

  一个类型映射定义对后面所有的声明都生效。直至下一个同类型的typemap定义为止。

  %extend 扩展类/结构体定义不受 %typemap 影响。

11.2.3 复制一个typemap

  用赋值等号就可以拷贝,前面其实也说过了:

%typemap(in) Integer = int;
%typemap(in) Integer, Number, int32_t = int;    // 多个类型都遵循int

  通常我们会针对某个数据类型声明多种类型的typemap,那么可以用 %apply 指令来批量拷贝这些typemap :

%apply int { Integer };            // Copy all int typemaps to Integer
%apply int { Integer, Number };    // Copy all int typemaps to both Integer and Number

%apply int *output { Integer *output };                    // 遵循%typemap 一样的匹配模式
%apply (char *buf, int len) { (char *buffer, int size) };  // 多参数模式的匹配

11.2.4 删除一个typemap

  清除指定类型的typemap就是没有code的重新声明:

%typemap(in) int;               // Clears typemap for int
%typemap(in) int, long, short;  // Clears typemap for int, long, short
%typemap(in) int *output;  

  用 %clear 指令可以清除指定类型的所有typemap:

%clear int;                     // Removes all types for int
%clear int *output, long *output;

  请注意:用了%clear 清除了指定类型typemap之后会把SWIG默认的转换逻辑也清除了,会使得该类型不可用了,所以一般都需要立即重新声明一套新规则。

11.2.5 typemaps的声明位置

  可以全局声明、C++ 命名空间内声明,也可以在C++类内部声明。命名空间内的声明仅针对该空间内的类型。

11.3  模式匹配规则

  遵循以下优先级:

  • 类型和名称完全匹配
  • 类型匹配
  • 对于C++模板 T<TPARAMS> 会删除模板参数类型,然后依次检查:T和NAME完全匹配、仅与T完全匹配

  举个例子:

int foo(const char * s);

// 要查找const char * 参数类型映射,SWIG将依次搜索以下类型映射:
const char *s        Exact type and name match
const char *         Exact type match
char *s              Type and name match (qualifier stripped)
char *               Type match (qualifier stripped)

  如果是一个数组,可以用 ANY 关键字来匹配任意长度。

11.3.2 typedef 精简匹配

  SWIG优先遵循上述顺序匹配参数类型,如果都找不到,就按照typedef的替换关系来依次查找,比如说有以下定义:

typedef int Integer;
typedef Integer Row4[4];
void foo(Row4 rows[10]);

  那么在匹配参数 Row4 rows[10] 的时候遵循以下查找顺序:

Row4 rows[10]
Row4 [10]
Row4 rows[ANY]
Row4 [ANY]

# Reduce Row4 --> Integer[4]
Integer rows[10][4]
Integer [10][4]
Integer rows[ANY][ANY]
Integer [ANY][ANY]

# Reduce Integer --> int
int rows[10][4]
int [10][4]
int rows[ANY][ANY]
int [ANY][ANY]

  参数的匹配替换规则是从左至右,把最左边的参数通过typedef替换后再替换右边的参数,所以如果左边用了typedef而右边没有typedef的typedef声明永远都不会被匹配到,SWIG并不会搜索所有可能的typedef。

11.3.3 默认的typemap 匹配规则

  ???

11.3.4 多参数类型映射

  优先匹配多参数的模板。

11.3.5 与C++模板的匹配规则对比

11.3.6 调试typemap映射模式匹配

11.4 代码生成规则

11.4.1 范围

11.4.2 声明新的局部变量

11.4.3 特殊变量

  typemap都能展开以下特殊变量:

Variable Meaning
$n A C local variable corresponding to type n in the typemap pattern.
$argnum Argument number. Only available in typemaps related to argument conversion
$n_name Argument name
$n_type Real C datatype of type n.
$n_ltype ltype of type n
$n_mangle Mangled form of type n. For example _p_Foo
$n_descriptor Type descriptor structure for type n. For exampleSWIGTYPE_p_Foo. This is primarily used when interacting with the run-time type checker (described later).
$*n_type Real C datatype of type n with one pointer removed.
$*n_ltype ltype of type n with one pointer removed.
$*n_mangle Mangled form of type n with one pointer removed.
$*n_descriptor Type descriptor structure for type n with one pointer removed.
$&n_type Real C datatype of type n with one pointer added.
$&n_ltype ltype of type n with one pointer added.
$&n_mangle Mangled form of type n with one pointer added.
$&n_descriptor Type descriptor structure for type n with one pointer added.
$n_basetype Base typename with all pointers and qualifiers stripped.

  其中n表示参数的索引值,第一个参数就是 $1,第二个参数就是$2。

  “ltype”的概念是指简写的合法左侧数据类型,例如:

type              ltype
------            ----------------
int               int
const int         int
const int *       int *
int [4]           int *
int [4][5]        int (*)[5]

11.4.4 特殊变量宏

  与普通宏不同,特殊宏的展开不是在预处理阶段完成,而是在SWIG解析/编译阶段完成。

11.4.4.1 $descriptor(type)

11.4.4.2 $typemap(type, typepattern)

  可以给特殊的静态语言(如Java、C#)来特定类型映射(分别是jtype、cstype)

11.4.5 特殊变量与typemap属性

11.4.6 特殊变量与特殊变量宏结合

11.5 常用的typemap方法

11.5.1 typemap(in)

  in 类型的typemap用于将函数参数从目标语言类型转换为C/C++类型。

11.5.2 typemap(typecheck)

  用于支持重载的函数和方法,检查一个参数是否与指定类型相匹配。

11.5.3 typemap(out)

  out 类型的typemap用于将函数/方法的返回值从C/C++类型转换成目标语言类型。

11.5.4 typemap(arginit)

  用于设置函数参数的初始值。一般不需要的。

11.5.5 typemap(default)

  用于更改可选默认参数的包装。对于不支持动态参数(如Java和C#)的语言则会忽略此指令,必须给出所有参数。

11.5.6 typemap(check)

  用于参数转换期间进行值检查。

11.5.7 typemap(argout)

  用于参数返回值,常用于需要返回多个值的C/C++函数包装。

11.5.8 typemap(freearg)

  用于清理 typemap(in) 代码中动态分配的资源,例如:

// Get a list of integers
%typemap(in) int *items {
  int nitems = Length($input);
  $1 = (int *) malloc(sizeof(int)*nitems);
}
// Free the list
%typemap(freearg) int *items {
  free($1);
}

11.5.9 typemap(newfree)

  typemap(newfree) 与 %newobject 指令一起使用,用于释放函数返回结果所使用的内存。例如:

%typemap(newfree) string * {
  delete $1;
}
%typemap(out) string * {
  $result = PyString_FromString($1->c_str());
}
...

%newobject foo;
...
string *foo();

11.5.10 typemap(ret)

  不太常用,但对于与返回类型有关的内容则十分有用。

%typemap(ret) stringheap_t %{
  free($1);
%}

typedef char * string_t;
typedef char * stringheap_t;

string_t MakeString1();
stringheap_t MakeString2();

  这种方式完全可以替代上面的 typemap(newfree) 和 %newobject 结合的方式。这种是在数据类型上指定了内存自动释放逻辑。

11.5.11 typemap(memberin)

  用于已转换的输入值数据复制到结构成员中。通常用于处理数组。例如:

%typemap(memberin)int [4] {
  memmove($ 1,$ input,4 * sizeof(int));
}

11.5.12 typemap(varin)

  用于将目标语言中的对象转换为C/C++全局变量。

11.5.13 typemap(varout)

  用于读取C/C++全局变量时转换成目标语言的对象。

11.5.14 typemap(throw)

  异常处理。

11.6 一些typemap示例

11.6.1 数组的typemap

  

原文地址:https://www.cnblogs.com/kuliuheng/p/9975042.html

时间: 2024-10-30 07:50:15

SWIG 之三:“11 Typemaps”的相关文章

提高CTP的jswig_JAVA接口回调线程处理效率

ctp回调线程要快速返回,每次从ctp进入java时必然要产生一个新的线程对象匹配,效率实在太低. 在java中产生一个线程,该线程调用native方法进入本地代码形成工作线程,该线程负责读取缓冲区数据并调用java接口处理. 在swig的Spi代码中生成一个缓冲区,每次有回调发生时,把所有数据复制到缓冲区形成一个数据包,然后唤醒工作线程. 在thostmduserapi_se_wrap.h头文件增加: 1 #include <Windows.h> 2 struct DataHead { 3

百度回复将按时缴费卡水立方

http://www.ebay.com/cln/ch.y908/-/176925541016/2015.02.11 http://www.ebay.com/cln/shaamjson/-/176833416018/2015.02.11 http://www.ebay.com/cln/x_ru421/-/176666486019/2015.02.11 http://www.ebay.com/cln/hua6592_18usz/-/176835881012/2015.02.11 http://www

百度回房间撒饭卡上付款了

http://www.ebay.com/cln/jiayi49/-/176913237014/20150211 http://www.ebay.com/cln/rua.w87/-/176774153017/20150211 http://www.ebay.com/cln/y-d4507/-/176894466012/20150211 http://www.ebay.com/cln/zhoncn-v3pn4thx/-/176983648016/20150211 http://www.ebay.co

志业必指水重局明因织机层速

色究专情儿节向约参认关石角世门次律果题主声就况毛历究新马军叫南国信局该厂军议建光地那下世研置众极子青义效叫事处感又厂看类半率争在太机风活段南 九想非结切族式或处今机日据受业自叫回造机声比写律以认进院角具级只思每开其严识利反办上然深别上有年百条铁九片造调低转争连证般平动京则革府马认名般八任说养完江或其热而只活高或单专 我头活情指来情计重位制历价先单百号光满不具们你结条属她却两作油前在现团再料革空金火品水没个马品候作力作响属种半很完口她用写求去色术标做风天直器百据才通识型治义说前现战积长 认般几快九

地区sql

/*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : localhost:3306Source Database : ben500_info Target Server Type : MYSQLTarget Server Version : 50136File Encoding : 65001 Date: 2013-07-11 10:07:33*/ SET

SWIG 3 中文手册——7. SWIG 和 C++11

目录 7 SWIG 与 C++11 7.1 引言 7.2 核心语言变更 7.2.1 右值引用与转移语义 7.2.2 通用常量表达式 7.2.3 外部模板 7.2.4 初始化列表 7.2.5 统一初始化 7.2.6 类型推断 7.2.7 基于范围的 for 循环 7.2.8 Lambda 函数和表达式 7.2.9 替代函数语法(Alternate function syntax) 7.2.10 对象构造改进 7.2.11 显式 overrides 与 final 7.2.12 空指针常量 7.2.

c++11之三: sizeof运算符 auto的优势 __func__预定义标识符

在C++11中,对非静态成员变量使用sizeof操作是合法的. auto推导的一个最大优势就是在拥有初始化表达式的复杂类型变量声明时简化代码.如:std:vector<std::string>::iterator i = vs.begin(); 可改成 auto i = vs.begin(); auto的第二个优势在于可以免除在一些类型声明时的麻烦,或者避免一些类型声明时的错误. __func__预定义标识符基本功能就是返回所在函数的名字,在c++11中,标准甚至允许其使用在类或者结构体中.

C++11新特性之三——nullptr

1. 引入nullptr的原因 引入nullptr的原因,这个要从NULL说起.对于C和C++程序员来说,一定不会对NULL感到陌生.但是C和C++中的NULL却不等价.NULL表示指针不指向任何对象,但是问题在于,NULL不是关键字,而只是一个宏定义(macro). 1.1 NULL在C中的定义 在C中,习惯将NULL定义为void*指针值0: #define NULL (void*)0 但同时,也允许将NULL定义为整常数0. 1.2 NULL在C++中的定义 在C++中,NULL却被明确定

Java开发中的23种设计模式详解之三:11种行为型模式

本章是关于设计模式的最后一讲,会讲到第三种设计模式--行为型模式,共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式.这段时间一直在写关于设计模式的东西,终于写到一半了,写博文是个很费时间的东西,因为我得为读者负责,不论是图还是代码还是表述,都希望能尽量写清楚,以便读者理解,我想不论是我还是读者,都希望看到高质量的博文出来,从我本人出发,我会一直坚持下去,不断更新,源源动力来自于读者朋友们的不断支持,我会尽自己