對於dll和lib兩者的關系,需要理解的一個概念是編譯時和運行時。
lib是編譯時的東西,在lib里面包含了方法名和方法所在的dll名字,可以用dumpbin -all XXX.lib查看內容。
dll是運行時的東西,里面是方法的實體。可以通過depends查看里面的方法和引用的dll文件等。
舉個例子方便理解:
有兩個project,A和B,A的輸出是一個動態dll,B的輸出是一個exe。B需要用到A里面的類和方法等。
首先是對A的處理:要把A的類或方法定義為“導出型”,即使用關鍵字_declspec(dllexport)。
如把一個類定義為導出類:class _declspec(dllexport) BaseTool{}
並且在A的project里面把配置類型設為dll動態庫,編譯完畢的時候可以看到A.dll和A.lib兩個文件。可以把A.dll和A.lib輸出到兩個不同的目錄下。如下圖所示:在“常規”->“輸出目錄”這邊設置輸出lib的文件夾,在“鏈接器”->"常規"->"輸出文件"這邊設置輸出的dll文件,注意一個是文件夾,一個是文件。

圖1

圖2
編譯完成之后,可以在指定的目錄下面找到.lib和.dll。
對於B,也需要一系列的處理:
首先是頭文件,需要把A里面對於類定義的頭文件夾放到項目屬性中的包含目錄下,如下圖:
圖3
這里面發現了一個比較有意思的事情,原先我以為只要把頭文件加到solution欄里面的項目頭文件處就可以了(如下圖),項目就會自動包含進來。沒想到不是這樣子的,關鍵還是在上圖的包含目錄里面加入頭文件所在的文件夾路徑,下圖解決方案里面的可能只是方便開發人員打開頭文件設置的,加不加不影響編譯和運行。
圖4
其次是附加庫目錄和附加依賴項:
圖5
圖6
附加庫目錄也可以通過圖3中的‘庫目錄’替代,兩者效果一樣。
附加依賴項是包含所需要的lib文件,可以指定全路徑,也可以只是指定名字,當只指定名字的時候,系統會在附加庫目錄或者庫目錄里面搜尋。如果不指定附加依賴項,也可以通過在代碼里面加入#pragma comment(lib,"XXX.lib")來實現。
到此為止,編譯應該是可以過了,但是具體運行的時候,會報出找不到dll的錯誤,這就是運行時錯誤了。
用dumpbin -all A.lib並重定向到一個txt文件中,可以看到lib里面有提到方法屬於哪個dll,因此需要讓它知道在哪里查找dll。
這時是運行時的事情了,需要設置系統環境變量,把dll所在目錄加進去就可以了。如果是debug模式,需要重啟VS。
其實lib文件可以不需要,而直接調用dll里面的方法。
采用LoadLibrary和GetProcAddress的方法,那樣子可以不需要lib文件。但是有一個重大影響,就是得知道方法名的准確名字。特別是對於c++輸出整個類的情形。因為c++輸出dll的時候,類的方法名都被打亂了,加入了很多的信息,所以一般情況下是不知道的,得通過def文件來重命名輸出的方法名。