當生成帶有SWIG的接口模塊時,生成的C/C++文件包含大量靜態樣板函數。因此,如果想要在同一個應用程序中使用許多單獨編譯的小接口來模塊化使用SWIG生成的接口,則由於這些重複的功能而導致大量的膨脹。當使用許多SWIG生成的模塊時避免重複的SWIG樣板
使用gcc的-ffunction-sections
選項,以及GNU鏈接器的--icf=safe
選項(-Wl,--icf=safe
編譯器),可以去掉一些重複的,但絕不是所有的(我認爲它不會合並任何有搬遷在其中 - 這些功能中的許多功能)。
我的問題:我想知道是否有辦法刪除更多這種重複的樣板,理想情況下不依賴於GNU特定的編譯器/鏈接器選項。
特別是,是否有SWIG選項/標記/說「不在每個輸出文件中包含樣板」?其實是 SWIG選項,-external-runtime
,它告訴它產生一個「樣板只」的輸出文件,但沒有明顯的方式來抑制包含在每個正常輸出文件中的副本。 [我認爲這樣的事情在SWIG中應該相當簡單,所以我很驚訝它似乎並不存在......但我似乎無法找到任何記錄。]
這是一個小例子:
鑑於接口文件swg-oink.swg
的模塊swt_oink
:
%module swt_oink
%{ extern int oinker (const char *x); %}
extern int oinker (const char *x);
...和類似的接口swg-barf.swg
爲swt_barf
:
%module swt_barf
%{ extern int barfer (const char *x); %}
extern int barfer (const char *x);
...和測試主文件,swt-main.cc
:
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
extern int luaopen_swt_oink (lua_State *);
extern int luaopen_swt_barf (lua_State *);
}
int main()
{
lua_State *L = lua_open();
luaopen_swt_oink (L);
luaopen_swt_barf (L);
}
int oinker (const char *) { return 7; }
int barfer (const char *) { return 2; }
和編譯他們像:
swig -lua -c++ swt-oink.swg
g++ -c -I/usr/include/lua5.1 swt-oink_wrap.cxx
swig -lua -c++ swt-barf.swg
g++ -c -I/usr/include/lua5.1 swt-barf_wrap.cxx
g++ -c -I/usr/include/lua5.1 swt-main.cc
g++ -o swt swt-main.o swt-oink_wrap.o swt-barf_wrap.o
那麼每個XXX_wrap.o
文件的大小是16KB左右,其中95%是樣板文件,最終可執行文件的大小大概是這些的總和,約爲39K。如果用-ffunction-sections
編譯每個接口文件,並鏈接到-Wl,--icf=safe
,最終可執行文件的大小是34KB,但仍然有很多重複(在可執行文件上使用nm
可以看到多次定義的大量函數,他們的來源,很明顯,對於大多數人來說,使用單一的全局定義是很好的)。
好點。我想這可以通過在名稱中包含某種ABI版本來處理,但將所有內容都設置爲靜態的確實簡單得多,並且不易出錯。增加優化確實也有助於減少開銷:在一個具有優化的實際案例中,每個目標文件的大小約爲4KB;仍然有點膨脹,但我認爲SWIG永遠不會是非常輕量級的...... – snogglethorpe