swig是Simplified Wrapper and Interface Generator的简称,它是一个能将C和C++的程序与其他各种高级语言诸如Perl,Python,Ruby和Tcl进行连结的开发工具。
swig的官方中文网站:http://www.swig.org/translations/chinese
什么是typemap
tymemap are an advanced customization feature that provide direct access to SWIG's low-level code generator. Not only that, they are an integral part of the SWIG C++ type system (a non-trival topic of its own). Typemaps are generally not a required part of using SWIG.
typemap是一个先进的定制化功能,可以提供直接访问SWIG的底层的代码生成器。除了这些,它也是SWIG C++类型系统完整的一部分。
typemap告诉SWIG如何去匹配Python对象和C/C++的函数参数,反之亦然。假设,我想实现一个类似与Python的join()函数,该函数接受一个列表,然后返回将列表中所有元素拼接而成的字符串,如下所示:
>>> import rgb2yuv
>>> print rgb2yuv.list2str([83, 120])
Sx
那对应的C++函数则为如下所示:
std::string list2str(unsigned char *yuyv_arr, int k)
相应的.i文件需要含有如下的关键语句
%apply (unsigned char *IN_ARRAY1, int DIM1) {(unsigned char *yuyv_arr, int k)};
其中需要注意的有以下几点:
1、apply后面跟的{(unsigned char *yuyv_arr, int k)}需要与.h文件中的函数声明保持完全一致,即便形参也需要保持一致;
2、IN_ARRAY1代表是一维数组,如果函数有两个数组参数,则为(unsigned char *IN_ARRAY1, unsigned char *IN_ARRAY1),而不能为(unsigned char *IN_ARRAY1, UNSIGNED char *IN_ARRAY2)。因为IN_ARRAY1和IN_ARRAY2分别代表一维数组和二维数组;
3、C++的实现需要将数组大小作为参数传进去,否则无法知道数组的大小。但是在Python调用时只需要传入第一个列表参数即可,如果传入第一个数组大小的参数则会报错。
实例1:想要实现rgb转yuv的一个函数,他的输入为rgb格式的数组,输出为yuv格式的数组。
rgb2yuv.c为
void rgb2yuyv(unsigned char *rgb_arr, int m, unsigned char *yuv_arr, int n)
{
unsigned char y0 = 0;
unsigned char y1 = 0;
unsigned char u = 0;
unsigned char v = 0;
unsigned char r1 = 0;
unsigned char g1 = 0;
unsigned char b1 = 0;
unsigned char r2 = 0;
unsigned char g2 = 0;
unsigned char b2 = 0;
int j = 0;
for(int i = 0; i < m; i += 6)
{
r1 = rgb_arr[i];
g1 = rgb_arr[i+1];
b1 = rgb_arr[i+2];
get_yuv(r1, g1, b1, &y0, &u, &v);
r2 = rgb_arr[i+3];
g2 = rgb_arr[i+4];
b2 = rgb_arr[i+5];
get_yuv(r2, g2, b2, &y1, &u, &v);
yuv_arr[j] = y0;
yuv_arr[j+1] = u;
yuv_arr[j+2] = y1;
yuv_arr[j+3] = v;
j += 4;
}
}
rgb2yuv.i为
%module rgb2yuv
%{
#define SWIG_FILE_WITH_INIT
#include "rgb2yuv.h"
%}
%include "numpy.i"
%init %{
import_array();
%}
%apply (double *IN_ARRAY1, int DIM1) {(double *vec, int m)};
%apply (double *ARGOUT_ARRAY1, int DIM1) {(double *vec2, int n)};
%include "rgb2yuv.h"
遇到的问题
1、<Swig Object of type 'uint32_t *' at 0x7f368eacbcf0>swig/python detected a memory leak of type 'uint32_t *', no destructor found.
解决方法:增加%include "stdint.i" 在.i文件的头部
2、TypeError: in method 'FpgaApi_get_register_value', argument 2 of type 'std::string &'
解决方法:将get_register_value()中std::string &改为const std::string &
3、TypeError: in method 'new_FpgaApi', argument 1 of type 'std::string const &'
解决方法:增加%include <std_string.i>在.i文件的头部。注意,这一行内容一定要先于对应的.h文件出现,否则该问题还是会出现。