2011-11-18 89 views
4

当生成带有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.swgswt_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可以看到多次定义的大量函数,他们的来源,很明显,对于大多数人来说,使用单一的全局定义是很好的)。

回答

2

我很确定SWIG没有这样做的选项。我现在在猜测,但我认为原因可能是由于使用不同版本的SWIG构建的模块的可见性而引起的关注。设想以下情况:

两个库X和Y都使用SWIG为其代码提供了一个接口。他们都选择在不同的翻译单元上使“SWIG胶水”可见,以减少代码大小。如果X和Y都使用相同版本的SWIG,这一切都会很好。如果X使用SWIG 1.1和Y使用SWIG 1.3,会发生什么?两个模块都能正常工作,但取决于平台如何处理共享对象以及语言本身如何加载它们(RTLD_GLOBAL?)在同一个VM中使用的两个模块的组合可能会发生一些非常糟糕的情况。

代码重复的代价非常低我怀疑 - 在VM和本机代码之间交换代价通常非常高,这可能会使指令缓存命中略有减少,尽管看到真实基准可能会很有趣。另一方面,这是代码,没有用户需要担心它,因为它全部是自动生成的,并且都正确地保留了为相应版本编写的接口。

+1

好点。我想这可以通过在名称中包含某种ABI版本来处理,但将所有内容都设置为静态的确实简单得多,并且不易出错。增加优化确实也有助于减少开销:在一个具有优化的实际案例中,每个目标文件的大小约为4KB;仍然有点膨胀,但我认为SWIG永远不会是非常轻量级的...... – snogglethorpe

1

我可能是有点晚了,但这里是一个解决办法:

  • 在痛饮(< = 1.3)有-noruntime命令行选项
  • 由于痛饮2.0 -noruntime被废弃了,所以现在一个应该将-DSWIG_NOINCLUDE传递给C预处理器 - 而不是swig本身

我完全不确定这是否正确,但它至少适用于我。我将在SWIG的邮件列表中澄清这个问题。

相关问题