1. 程式人生 > >windows應用程式【三】靜態連結庫和動態連結庫

windows應用程式【三】靜態連結庫和動態連結庫

在寫c語言程式時,我們會呼叫標頭檔案 呢麼標頭檔案理論上一定有實現方法 我們可以去檢視標頭檔案一般在你安裝vc目錄下的/vc98/include 來看一下windows.h

但是我們發現windows.h中只是一些定義與宣告 呢麼我們再來看windows.h的標頭檔案

我們開啟winuser 查詢messagebox

我們可以發現有許多messagebox 但是還是找不到實現的方法

其實原因很簡單 這些windows.h標頭檔案的大多數函式是與作業系統交流的 如果我們可以看到這些就可以輕易的瞭解作業系統的底層 但是微軟肯定不想我們這樣做 於是產生了.lib也就是連線庫 將實現方法封裝在其中 只留出介面供我們呼叫

下面我們來寫一個靜態庫來把它呼叫起來

建立標頭檔案宣告變數 

 

建立c語言檔案去實現add也就是加法函式 然後我們編譯連結執行

這是因為我們沒有入口函式需要去尋找入口 但是我們可以看到已經產生了.lib檔案

 現在我們已經將函式全部封裝起來了 現在我們來在建立一個工程進行呼叫

現在我們新增一個新的工程

此時出現報錯 原因是編譯器不知道去哪裡找這個標頭檔案

但是stdio卻能知道去哪裡找 因為這些標頭檔案是已經規定好路徑的 

可以在這裡新增入你的標頭檔案的路徑 也可以如圖輸入路徑

此時可以編譯通過 卻無法執行 這是因為我們沒有將連結庫檔案 和我們的程式碼聯絡起來

 在所有的預處理指令中,#pragma 指令可能是最複雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。 #pragma comment( comment-type ,["commentstring"] ) comment-type是一個預定義的識別符號,指定註釋的型別,應該是compiler,exestr,lib,linker之一。 commentstring是一個提供為comment-type提供附加資訊的字串。 常用的lib關鍵字,可以幫我們連入一個庫檔案

於是加入

 

 

下面來看動態庫

因為不同的程式需要的.lib肯定會有一部分重因此我們就需要去動態連結庫 去呼叫相同的程式碼

__declspec(dllexport)

此修飾符將一個函式聲名為匯出函式,就是說這個函式要被其他程式呼叫,即作為DLL的一個對外函式介面。

其實與建立靜態庫的建立過程一樣 只是需要在這裡改為 這樣去寫標頭檔案

 

但是此時檔案會生成.lib 和 .dll 但是在動態庫中函式的內容實際是在.dll中 .lib只是一個索引的作用

 動態lib & 靜態lib

靜態lib將匯出宣告和實現都放在lib中。編譯後所有程式碼都嵌入到宿主程式 動態lib相當於一個h檔案,是對實現部分(.dll檔案)的匯出部分的宣告。編譯後只是將匯出宣告部分編譯到宿主程式中,執行時候需要相應的dll檔案支援

Windows搜尋DLL的順序

(1)當前程序的可執行模組所在的目錄; (2)當前目錄; (3)Windows 系統目錄,通過GetSystemDirectory 函式可獲得此目錄的路徑;    C:\Windows\System32    C:\Windows\SysWow64 //64位機器,32位dll (4)Windows 目錄,通過GetWindowsDirectory 函式可獲得此目錄的路徑; (5)PATH 環境變數中列出的目錄。 

MessageBox在哪?

大部分Windows API 都在下面幾個DLL當中: KERNEL32.DLL ---- 低階核心函式。使用他可以完成記憶體管理、任務管理、資源控制等。 USER32.DLL------於windows管理有關的函式。訊息、選單、游標、計時器、通訊和其他大多數非現實函式都可以從這裡找到 GDI32.DLL-------圖形裝置介面庫。於裝置輸出有關的函式:大多數繪圖、顯示場景、圖元檔案、座標及其字型函式都可以從這裡找到。 

靜態庫(lib) VS 動態庫(dll)

靜態庫會顯著增加exe模組的體積; DLL獨立於程式語言,大多數windows程式設計環境都允許主程式呼叫DLL中的函式; exe模組呼叫動態庫的匯出函式時,需要先載入DLL,有一定的效能損失; 靜態庫可以避免執行程式的系統缺少DLL或DLL地獄問題造成程式無法正常執行