痛苦的DLL

有时候你必须得用到DLL。

比如,假如你想在python或者java中调用C/C++的code。那么这些native code必须得编译成一个DLL。
再比如,VC对单个exe/lib/pdb的文件大小有2GB的限制,这些限制很容易在debug版中hit到。

最大的麻烦在于将一个DLL拆成多个DLL。windows下要求DLL之间不能有循环依赖。举个例子,假如你实现了一个vfs.dll。这个dlll声明了一个IFileSystem的interface,和一个FileSystemFactory的Singleton。然后在其它的dll中有IFileSystem具体实现。比如hdfs.dll,httpfs.dll,nfs.dll…… 与Linux不同的是,Windows下编译hdfs.dll等这些dll的时候,它所用到的所有符号必须要能找到具体的实现。也就是说,这些dll必须要链接到vfs.dll。vfs.dll必须把所有实现时所需要用到的函数、类、全局变量都导出。举个例子,假设vfs.dll和其它的dll都用到了zlib。那么要么zlib被全部打包进vfs.dll,那么zlib也必须编译成一个dll。否则,如果这些dll都静态链接到zlib,那么zlib中的全局变量就会有多份拷贝。

不是所有的符号都可以导出。一个典型的麻烦例子就是STL里的容器。How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object . 简单点说:std::string以及STL里除了std::vector以外的所有容器都是不可导出的。所以,一般来讲,DLL的interface里最好不要有STL的数据结构。这个限制挺让人恼火的。

追根溯源,DLL并没有weak symbol这样的东西。于是template class里的静态变量就会在同一个进程里有多份实例,每个dll里都可有一个。一个典型的例子就是std::string::npos。唯一的解决办法就是显式的对模板类实例化。但是对于STL来说,这个过于复杂,不大可能做到。




此博客中的热门博文

在windows下使用llvm+clang

少写代码,多读别人写的代码

tensorflow distributed runtime初窥