靜態庫在連接階段,會將彙編生成的目標文件.o與引用到的庫一塊兒連接打包到可執行文件中。所以對應的連接方式稱爲靜態連接。windows
首先在頭文件下添加一個頭文件static.h
頭文件static.h的內容以下:函數
int sum(int a, int b);//聲明函數
在源文件下添加一個源文件static.cpp,內容以下:操作系統
#include "static.h" #include "stdafx.h" int sum(int x, int y){ return x + y;}
在菜單欄選擇「生成」->「生成解決方案」就能夠了。3d
而後打開工程文件夾,在Debug目錄下(編譯選擇的是默認的Debug和Win32)就能夠看到一個和項目名稱相同的lib文件:code
這樣供給別人調用的lib文件就生成好了,下面講如何調用這個靜態庫文件。blog
首先新建另外的項目TestCallLib1,這個項目將使用咱們剛剛生成的靜態庫
索引
將頭文件static.h和靜態庫TestLib1.lib拷到TestCallLib1\TestCallLib1目錄下
接口
首先將主函數寫好內存
有兩種方法調用靜態庫:unicode
運行獲得結果!
建立動態庫關鍵是導出函數,DLL中導出函數的聲明有兩種方式:
新建項目win32,應用程序類型選擇dll
須要本身手動添加四個文件
頭文件dllgenerator.h,內容:
int Add(int, int);int Mul(int, int);
函數定義文件dllgenerator.cpp,內容:
int Add(int a, int b){return a + b;} int Mul(int c, int d){return c * d;}
dllmain.cpp : 定義 DLL 應用程序的入口點
// dllmain.cpp : 定義 DLL 應用程序的入口點。 #include <windows.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
需包含庫<windows.h>,裏面有不少與生成動態庫的相關函數和參數
創建源文件Source.def(劃重點)
在此文件第一行引號中填你的項目名稱便可,EXPORTS下面列出要生成的函數名稱 格式:「名稱 @序號」)
LIBRARY "TestDll1" EXPORTS Add @1 Mul @2
點擊菜單欄 生成 -> 生成解決方案,咱們的動態庫就生成成功了
新建項目過程同上!這裏的關鍵是頭文件中須要加入關鍵字__declspec(dllexport),這個關鍵字是導出函數的關鍵!
添加lib.h和lib.cpp函數
生成後一樣看見.dll文件和.lib文件
新建項目DLLTestor,將剛剛生成的.dll、.lib、.h文件拷貝到DLLTestor\DLLTestor文件下( .lib、.h 文件不是必須拷入的,我這裏並無拷入)
工程調用dll時首先在工程文件目錄中查找dll,找不到後在C:\Windows\System32 中找。因此咱們本身項目簡單調用dll時就把生成的dll文件複製到工程目錄中,若是常常用能夠把dll文件放到C:\Windows\System32中
調用動態庫是調用 .dll、 .lib、 .h 三個文件
編好代碼並設置.lib和.h文件的調用路徑
右鍵「目錄」「屬性」選擇「連接器」->「輸入」,在「附加依賴項」這裏添加要調用的lib文件的名字:TestDll1.lib
運行獲得結果
動態加載是指在生成可執行文件時不將全部程序用到的函數連接到一個文件,由於有許多函數在操做系統帶的dll文件中,當程序運行時直接從操做系統中找。
而靜態加載就是把全部用到的函數所有連接到exe文件中。動態加載是隻創建一個引用的接口,而真正的代碼和數據存放在另外的可執行模塊中,在運行時再裝入;
而靜態加載是把全部的代碼和數據都複製到本模塊中,運行時就再也不須要庫了。
#include "stdafx.h" #include "dllgenerator.h" #include "windows.h" int _tmain(int argc, CHAR* argv[]){ printf("Hello World!\n"); HMODULE hmod = LoadLibrary("TestDll1.dll"); // //用於加載dll typedef int(*LoadProc)(int x, int y); LoadProc Load_proc = (LoadProc)GetProcAddress(hmod, "Add"); //GetProcAddress()用於得到函數地址 int iRet = Load_proc(3, 5); //獲得地址後調用該函數,返回較大值 printf("the Add the value is:%x\n", iRet); return 0; }
須要理解調用動態庫主要用到三個函數,加載LoadLibrary、調用GetProcAddress、釋放FreeLibrary!
別忘了在右鍵「目錄」「屬性」選擇「連接器」->「輸入」,在「附加依賴項」這裏添加要調用的lib文件的名字:TestDll1.lib
你們在製做過程當中可能會遇到以下的問題
這是字符集的問題,具體的解決方案是:右鍵項目->屬性
把字符集從unicode改爲多字節字符集。
目前以lib後綴的庫有兩種,一種爲靜態連接庫(Static Libary,如下簡稱「靜態庫」),另外一種爲動態鏈接庫(DLL,如下簡稱「動態庫」)的導入庫(Import Libary,如下簡稱「導入庫」)。靜態庫是一個或者多個obj文件的打包,因此有人乾脆把從obj文件生成lib的過程稱爲Archive,即合併到一塊兒。好比你連接一個靜態庫,若是其中有錯,它會準確的找到是哪一個obj有錯,即靜態lib只是殼子。動態庫通常會有對應的導入庫,方便程序靜態載入動態連接庫,不然你可能就須要本身LoadLibary調入DLL文件,而後再手工GetProcAddress得到對應函數了。有了導入庫,你只須要連接導入庫後按照頭文件函數接口的聲明調用函數就能夠了。導入庫和靜態庫的區別很大,他們實質是不同的東西。靜態庫自己就包含了實際執行代碼、符號表等等,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。
通常的動態庫程序有lib文件和dll文件。lib文件是必須在編譯期就鏈接到應用程序中的,而dll文件是運行期纔會被調用的。若是有dll文件,那麼對應的lib文件通常是一些索引信息,具體的實如今dll文件中。若是隻有lib文件,那麼這個lib文件是靜態編譯出來的,索引和實現都在其中。