今天去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 什么時候同時需要動態庫與靜態庫的支持?(這個望能有熱心人多多指點 :)