SWIG使用简明教程(一)

本文介绍如何使用SWIG在Python环境中调用C++模块,包括SWIG接口描述文件的编写,指令使用,以及对C/C++声明的处理。特别关注SWIG在不同数据类型转换,全局变量和常量处理上的细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写作目的:结合工作需要——封装C++模块在Python下调用。对SWIG官方文档相关部分做了翻译和归纳。

官方文档:http://www.swig.org/Doc4.0/index.html

使用环境:window、python3.6、swigwin-4.0.1

不足之处欢迎斧正。

使用SWIG

swig [ options ] filename

 SWIG接口描述文件xxx.i or xxx.swg

SWIG接口描述文件用来告诉SWIG接口的导出内容、信息和规则等;

eg:

%module mymodule 
%{
#include "myheader.h"
%}
// Now list ISO C/C++ declarations
int foo;
int bar(int x);
...

通过 %module 命令声明模块名称

%{ ... %}中的所有内容将会拷贝到SWIG生成的wrapper文件,该部分被用来包含头文件、声明。SWIG不会解析里面的内容,用户需要确保内容的正确性。

 SWIG输出

SWIG输出的是模块所用到的C/C++包裹文件。SWIG会根据使用的语言生成附加文件.默认情况下,输入file.i文件会生成file_wrap.cxx文件。输出的C/C++文件名可通过 -o 参数指定。

eg:

swig -c++ -python -o example_wrap.cpp example.i

 SWIG指令

绝大多数SWIG指令是以‘%’前缀开头,用来和C声明做区分。SWIG指令用于提示或改变SWIG的解析行为。

 解析局限

尽管SWIG能够解析大多数C/C++声明,但是它没有提供全C/C++解析的支持,这些限制大多数都与C++高级功能有关。

不支持的功能如下:

  • 非常规类型声明。 例如,SWIG不支持以下声明(即使这是合法的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 ++源文件(.C,.cpp或.cxx文件中的代码)运行SWIG生成包裹文件。 通常的方法是提供SWIG头文件以解析C ++定义和声明。 主要原因是,如果SWIG解析作用域定义或声明(对于C ++源文件是正常的),则将其忽略,除非先前已解析符号的声明。 例如:
/* bar not wrapped unless foo has been defined and 
   the declaration of bar within foo has already been parsed */
int foo::bar(int) {
  ... whatever ...
}
  • 尚未完全支持C ++的某些高级功能,例如嵌套类。

打包简单的C声明

SWIG通过创建一个与C程序中使用声明的方式紧密匹配的接口来包装简单的C声明。 例如,考虑以下接口文件:

%module example

%inline %{
extern double sin(double x);
extern int strcmp(const char *, const char *);
extern int Foo;
%}
#define STATUS 50
#define VERSION "1.1"

该文件中有两个函数,sin()和strcmp(),全局变量Foo,两个常量STATUS和VERSION,SWIG创建扩展模块时,这些声明分别可以作为脚本语言函数,变量和常量进行访问。

>>> example.sin(3)
5.2335956
>>> example.strcmp('Dave', 'Mike')
-1
>>> print example.cvar.Foo
42
>>> print example.STATUS
50
>>> print example.VERSION
1.1

SWIG会尽可能创建一个与基础C / C ++代码紧密匹配的接口。 但是,由于语言,运行时环境和语义之间的细微差异,因此并非总是可能做到这一点。 

基本类型处理

为了构建接口,SWIG必须将C / C ++数据类型转换为目标语言中的等效类型。 转换过程涉及一定数量的类型强制。

大多数脚本语言提供使用C中的int或long数据类型实现的单个整数类型。以下列表显示了SWIG将在目标语言中与整数进行相互转换的所有C数据类型:

int
short
long
unsigned
signed
unsigned short
unsigned long
unsigned char
signed char
bool

注意:

C中的16位短可以被提升为32位整数。 当整数朝另一个方向转换时,该值将转换回原始的C类型。 如果该值太大而无法容纳,它将被无声地截断。

unsigned char和signed char是特殊情况,它们被当作小的8位整数处理。 通常,char数据类型映射为一个单字符ASCII字符串。

布尔数据类型强制转换为0和1的整数值,除非目标语言提供特殊的布尔类型。

使用大整数值时需要格外小心。32位无符号整数(可能显示为较大的负数)可能会出现类似的问题。

根据经验,可以安全使用int数据类型以及char和short数据类型的所有变体。 对于无符号的int和long数据类型,在用SWIG包装程序之后,需要仔细检查程序的正确操作。

SWIG可识别以下浮点类型:

float
double

char数据类型被映射到以单个字符结尾的NULL终止ASCII字符串。

char *数据类型以NULL终止的ASCII字符串处理。

目前,SWIG对Unicode和宽字符字符串(C wchar_t类型)提供了有限的支持。

 全局变量

%module example
double foo;

在Python中,必须通过称为cvar的特殊变量对象访问所有全局变量。

# Python
cvar.foo = 3.5                  # Set foo to 3.5
print cvar.foo                  # Print value of foo

 常量

常量可以使用#define,枚举或特殊的%constant指令创建常量。下面列出了一些有效的常量声明:

#define I_CONST       5               // An integer constant
#define PI            3.14159         // A Floating point constant
#define S_CONST       "hello world"   // A string constant
#define NEWLINE       '\n'            // Character constant

enum boolean {NO=0, YES=1};
enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG,
             SEP, OCT, NOV, DEC};
%constant double BLAH = 42.37;
#define PI_4 PI/4
#define FLAGS 0x04 | 0x08 | 0x40

未完待续...

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bitQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值