編譯過程
首先,編譯器會執(zhí)行預(yù)處理,也就是所有以"#"開頭的預(yù)處理語句。
->優(yōu)化階段->生成匯編并轉(zhuǎn)換到機器語言->生成obj文件
其中每個cpp文件都是單獨的編譯單元,都是獨自生成相對的obj文件
后期才通過linker進行相互的鏈接。
預(yù)處理相關(guān)
大致有#include:單純的將頭文件內(nèi)的所有文本復(fù)制到所在的位置。
#define:單純的文本替換。
#if:進行條件判斷,若滿足條件,則if所包含的文本有效,反之則無效。
預(yù)處理相關(guān)設(shè)置:
1 生成預(yù)處理后的文件,但不能生成obj
2 生成匯編代碼文件
3 設(shè)置優(yōu)化級數(shù),使生成的obj、asm等文件不包含優(yōu)化代碼
優(yōu)化等級與runtime check掛鉤
首先,要理解鏈接是將多個obj文件鏈接為一個exe文件,并解決在某個文件中引用另一個文件中的符號相關(guān)的問題。
鏈接時,linker首先決定各個obj文件在最終exe文件中的位置,然后訪問所有obj文件的地址表,將其全部地址進行重定向,然后遍歷所有obj文件中未解決的符號,生成未解決符號表,并在符號表中查找匹配的符號,將未解決符號表填補完成,最后對每個obj文件進行排序即完成。
鏈接方式:
1 靜態(tài)鏈接:在鏈接時,就查找obj中缺失的目標函數(shù),再去靜態(tài)庫中查找相應(yīng)的obj對象,直接包含在程序內(nèi),運行時不用再次查詢。但這里在庫中查找的obj對象是一整個,也就是說即使只使用了它其中一個函數(shù),還是會包含obj中其他所有的函數(shù),導致內(nèi)存大量浪費;且每次更新庫,都需要將庫重新編譯并鏈接一遍。但優(yōu)點在于運行時不用查詢,運行速度快。
2 動態(tài)鏈接:在運行時,檢測到未解決符號,再去查找包含相應(yīng)符號的obj文件,并且一個obj只用加載一次,空間使用率高,且更新時不用再次編譯鏈接。但運行速度比不上靜態(tài)庫。
下面是動態(tài)鏈接的過程:
假設(shè)現(xiàn)在有兩個程序program1.o和program2.o,這兩者共用同一個庫lib.o,假設(shè)首先運行程序program1,系統(tǒng)首先加載program1.o,當系統(tǒng)發(fā)現(xiàn)program1.o中用到了lib.o,即program1.o依賴于lib.o,那么系統(tǒng)接著加載lib.o,如果program1.o和lib.o還依賴于其他目標文件,則依次全部加載到內(nèi)存中。當program2運行時,同樣的加載program2.o,然后發(fā)現(xiàn)program2.o依賴于lib.o,但是此時lib.o已經(jīng)存在于內(nèi)存中,這個時候就不再進行重新加載,而是將內(nèi)存中已經(jīng)存在的lib.o映射到program2的虛擬地址空間中,從而進行鏈接(這個鏈接過程和靜態(tài)鏈接類似)形成可執(zhí)行程序。
庫相關(guān)
1 編寫庫:
①新建空項目
②編寫相應(yīng)的.h和.cpp文件實現(xiàn)功能(具體待以后總結(jié))
③項目屬性中設(shè)置
④build過后,lib文件就生成了
2 引用庫:
將要使用庫的項目中新建兩個文件夾(不建也可以)include和lib
將上面編寫的.h和.cpp復(fù)制到inclde中,lib復(fù)制到lib中
在包含目錄中添加包含.h和.cpp的文件夾路徑
附加庫目錄中添加lib的路徑,并添加依賴項
然后在項目中引用.h即可使用庫中函數(shù);要注意的是link若報錯,則添加忽略項即可。
2 動態(tài)庫:
首先項目屬性設(shè)置為輸出dll文件。
編寫相應(yīng)的.h和.cpp文件實現(xiàn)功能。
要注意指定導出的變量或函數(shù),有以下方法:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
//以上是將declspec用宏定義包裝(別名),dllexport意思是被此宏修飾的變量或函數(shù)是要從dll中導出去的
//而dllimport的意思是要從別的dll中讀取進來
//此方法不能有.def文件,一定不能有!
//導出類
class MYDLL_API Rectangle
{public:
double getarea(double w, double h);
void print();
};
//導出函數(shù),變量也一樣可以導出
MYDLL_API int mysum(int a, int b);//注意是寫在函數(shù)前面!
//一般都在.h中寫好,但在.cpp中寫也一樣,注意只能有一處寫,不然報錯
//導出類若有了修飾,則它的成員函數(shù)不需要寫這個修飾
還有就是編寫.def文件,并加入到設(shè)置
內(nèi)容如下:
LIBRARY MyDll(dll的名稱,是真的dll的名稱哦,引用dll時都用這個名稱,若不用def則就是生成文件的名字)
EXPORTS
函數(shù)名1(如MyAdd)
函數(shù)2...
引用動態(tài)庫:
//只需要Dll文件放在exe文件同一目錄下即可
#include#includetypedef int(*Pmysum)(int a, int b);//定義一個指針函數(shù)類型
int main()
{HMODULE Hdll = LoadLibrary(L"Add.dll");//獲取dll地址
if (Hdll != NULL)
{Pmysum mysunm = (Pmysum)GetProcAddress(Hdll, "Sub");//獲取dll中的函數(shù)地址
if (mysunm != NULL)
{std::cout<< "調(diào)用兩變量相加函數(shù):"<< mysunm(7, 2);
}
}
FreeLibrary(Hdll);//卸載dll
return 0;
}
第二種方法是,將.h、.lib和.dll都放在某一目錄中,在項目屬性中,包含目錄指定.h,附加庫目錄指定.lib,附加依賴項指定.lib,.dll放在exe同一目錄下。
//若只指定包含目錄.h,則用以下方法
#pragma comment(lib,"MyDll.lib) (此方法需要將該lib文件放到與exe同目錄下)
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧