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文件出現,否則該問題還是會出現。