假設我們有一個頭文件看起來像:
#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <functional>
#include <iterator>
struct A {
A(const std::string& v) : val(v) {}
A(const A&) = default;
A() = default;
std::string val;
};
inline std::ostream& operator<<(std::ostream& in, const A& o) {
return in << o.val;
}
inline void run(const std::vector<A>& in) {
std::copy(in.begin(), in.end(), std::ostream_iterator<A>(std::cout, "\n"));
}
#endif
我們希望把它包起來,使得run
可以被稱爲與字符串列表或std::vector<A>
交替。
鑑於語言不可知性是一個陳述的目標,實現這一目標的最好方法是引入更多的C++,以幫助進行某些類型轉換和重載。
我們可以初步包住頭文件簡單的東西,如:
%module test
%include <std_vector.i>
%include <std_string.i>
%{
#include "test.h"
%}
%template(AVec) std::vector<A>;
%include "test.h"
,然後足以運行我們的Python測試用例上半年:
import test
test.A("")
v1=test.AVec(2,test.A("testing"))
print type(v1)
test.run(v1)
# Here onwards needs some more work though...
v2=["hello", "world", "isn't", "this", "fun"]
print type(v2)
test.run(v2)
要開始工作在這個測試案例的後半部分,我們需要調整SWIG接口。我將通過添加一個函數來實現這個功能,這個函數在包裝器內部以及一個利用SWIG默認的std::vector<std::string>
的默認類型映射的過載。
通過添加:
%{
// Some glue to trivially convert types
std::vector<A> convert(const std::vector<std::string>& in) {
std::vector<A> ret;
std::copy(in.begin(), in.end(), std::back_inserter(ret));
return ret;
}
%}
%inline %{
// An overload.
void run(const std::vector<std::string>& in) {
run(convert(in));
}
%}
爲我們添加了作品所提供的目標語言超載初始SWIG接口端具有的std::vector
合適的理解。 (大部分我檢查似乎)。
隨着我測試SWIG的版本,運行SWIG本身時出現警告,給出了有關鏡像過載的(僞)警告。這個警告似乎是不正確的,因爲生成的代碼確實根據給定的參數選擇了正確的重載。
在界面文件中使用與%inline
一起添加的過載是迄今爲止最快/最簡單的方式來啓動和運行。當然,它要求複製/轉換開銷和根據功能手動寫入重載。用typemap做它只需要編寫一個單一的類型圖,但是要以獨立於目標語言的方式很難做到。