最近在學(xué)習(xí)OSG庫(kù)的時(shí)候發(fā)現(xiàn)隨便打開一個(gè)頭文件,每個(gè)類的聲明中類名之前都會(huì)插入一個(gè)宏定義OSG_EXPORT
class OSG_EXPORT MatrixTransform : public Transform
查看這個(gè)宏定義主要涉及到兩個(gè)dll文件的關(guān)鍵字__declspec(dllexport)
和__declspec(dllexport)
# if defined( OSG_LIBRARY_STATIC )
# define OSG_EXPORT
# elif defined( OSG_LIBRARY )
# define OSG_EXPORT __declspec(dllexport)
# else
# define OSG_EXPORT __declspec(dllimport)
# endif
一番查找資料后總結(jié)如下:
頭文件的作用
- 首先要知道我們?yōu)槭裁匆褂妙^文件?
- 頭文件可以理解為是C++的接口文件亭敢,我們?cè)诰幾g這個(gè)工程的時(shí)候不僅需要它的cpp文件還需要頭文件,并且在我們給其他工程鏈接完動(dòng)態(tài)庫(kù)后,要想使用動(dòng)態(tài)庫(kù)里方法時(shí)是通過(guò)提供此動(dòng)態(tài)庫(kù)的頭文件的方式
#include 動(dòng)態(tài)庫(kù)的頭文件.h
- 因此頭文件需要區(qū)分是給自己編譯用還要給別人提供方法用
dllexport
- 字面意思暴露dll中的變量或方法
- 編譯dll文件的時(shí)候,在dll頭文件聲明的變量名稱前添加dllexport膏燃。表明這些東西可以被其他工程使用燕锥,即是把 dll中的相關(guān)代碼(類预烙,函數(shù),全局變量)暴露出來(lái)為以后其他應(yīng)用程序使用。
dllimport
- 字面意思插入dll中的變量或方法
- 是在其他工程需要使用dll內(nèi)相關(guān)內(nèi)容時(shí)使用的關(guān)鍵字颂碘。當(dāng)其他工程要使用dll 內(nèi)部代碼(類邀层,函數(shù)返敬,全局變量)時(shí),只需要在dll頭文件中聲明的變量名稱前添加dllimport關(guān)鍵字即可,作用是把dll中的相關(guān)代碼插入到應(yīng)用程序中寥院。
_declspec(dllexport)
與_declspec(dllimport)
是相互呼應(yīng)劲赠,只有在dll內(nèi)部用dllexport作了聲明,才能在外部函數(shù)中用dllimport導(dǎo)入相關(guān)代碼秸谢。
常用方法
- 因?yàn)橥粋€(gè)頭文件里的變量需要兩種不同的聲明前綴,因此一般通過(guò)一個(gè)宏
DLL_BUILD
來(lái)區(qū)分
#ifdef DLL_BUILD
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
- 在生成dll工程中,工程屬性下記得要設(shè)置預(yù)處理器定義
BUILD_DLL
告訴編譯器該接口需要暴露 - 在外部調(diào)用這個(gè)dll的工程中凛澎,包含這個(gè)頭文件,此時(shí)
BUILD_DLL
宏沒(méi)有定義估蹄,所以用了dllimport這個(gè)關(guān)鍵字预厌,是告訴編譯器該接口是從外部導(dǎo)入的
插曲: 對(duì)于動(dòng)態(tài)庫(kù)本身必須使用關(guān)鍵字__declspec(dllexport),對(duì)于應(yīng)用程序,不使用 __declspec(dllimport)也能正確編譯代碼,但使用 __declspec(dllimport) 使編譯器可以生成更好的代碼
回到開頭OSG庫(kù)的代碼中
- OSG同時(shí)提供動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù), 且都使用一個(gè)頭文件,靜態(tài)庫(kù)頭文件中的聲明是不需要任何前綴關(guān)鍵字,因此為了解決關(guān)鍵字的沖突使用了
OSG_LIBRARY_STATIC
和OSG_LIBRARY
來(lái)區(qū)分
# if defined( OSG_LIBRARY_STATIC )
# define OSG_EXPORT
# elif defined( OSG_LIBRARY )
# define OSG_EXPORT __declspec(dllexport)
# else
# define OSG_EXPORT __declspec(dllimport)
# endif
- 編譯動(dòng)態(tài)庫(kù)時(shí),頭文件需要定義
OSG_LIBRARY
宏 - 編譯靜態(tài)庫(kù)時(shí),頭文件需要定義
OSG_LIBRARY_STATIC
宏 - 其他程序使用庫(kù)時(shí),頭文件不需要定義任何宏,只在遍歷名稱前加
OSG_EXPORT
即可