今天去OGRE的官方网站看到了1.4.0[Eihort]的release note, 其中有一条说是,此版本支持静态库和动态库的编译,由此引发了厄的以下遐想。
前提:
ogre中可以在静态库和动态库的编译的是一些较为通用的,具有可替换性的组件,如: 渲染器部分,它基于一个公共接口,实现了具体的DirectX和OpenGL的各版本的具体组件.
example:
// in IRenderer.h
class Renderer {
public:
virtual bool begin(Rect* pArea) =0;
virtual void end() =0;
};
// in DxRenderer.h
// singleton
class DxRenderer: public Renderer {
public:
virtual bool begin(Rect* pArea);
virtual void end();
};
// in OGLRenderer.h
// singleton
class OGLRenderer: public Renderer {
public:
virtual bool begin(Rect* pArea);
virtual void end();
};
// user code on dynamic/static library
Renderer* r = createRenderer(Dx9_Version); // need export when by dynamic library
r->begin(0);
r->end();
在Windows下编译代码为两种形式的细节如下:
由于打算以LoadLibrary, FreeLibrary, GetAddressSymbol的方式主动载入动态库,所以,大多数情况下不需要导出类的实例成员,不想留给外部使用的成员函数只需声明在protected区.
Y: Yes
N: No
M: Maybe
纯虚 导出成员吗 需要另外的创建函数吗 需要外加特别的函数吗
静态库: Y N M N
动态库: Y N Y (createRenderer之类) Y (DllMain)
由此归纳出,在Windows下,编译基于抽象类组件为动态库比之编译为静态库只需加上createRenderer和DllMain函数,同时声明createRenderer为导出函数。当然连接器的选项就不同了,但是编译器的选项基本一致。
所以,可以做到,先编译出静态库的.lib文件,然后要得到对应的.dll时,只需另外编译createRenderer和DllMain,然后使用linker从.lib + createRenderer + DllMain就可作出.dll来。大大节省获得.dll的时间。
不过我看到OGRE可是两种情况下各做一次编译。
所以在遇到static/dynamic库取舍不定时,至少自问:
a 什么时候需要把库做成动态库?(此问题上面基本已经回答了)
b 什么时候同时需要动态库与静态库的支持?(这个望能有热心人多多指点 :)