本篇主要講述動态庫的開發、動态庫的測試與調用、添加log日志記錄的應用。
動态庫原理淺析
1. 動态庫是什麼,它有什麼作用? |
Windows系統平台上提供了一種完全不同的較有效的程式設計和運作環境,你可以将獨立的程式子產品建立為較小的DLL(Dynamic Linkable Library)檔案,并可對它們單獨編譯和測試。在運作時,隻有當EXE程式确實要調用這些DLL子產品的情況下,系統才會将它們裝載到記憶體空間中。這種方式不僅減少了EXE檔案的大小和對記憶體空間的需求,而且使這些DLL子產品可以同時被多個應用程式使用。詳見文檔《Win32環境下動态連結庫(DLL)程式設計原理》。 |
2. 動态庫的導出 |
動态庫的導出有兩種方法: (1) __declspec(dllexport)intMyFunction(int n); 這樣就可以将動态庫中的函數MyFunction()導出了。 (2) 需要一個Des檔案,通過該檔案來導出動态庫。 (Master沒細說這種方法,不過說了這兩種方法都較常用) 說明:在後面的例程中将使用第一種導出方法,并且将__declspec(dllexport)int放到宏定義中去。 |
3. 與DLL子產品建立連結(應用程式加載動态庫) |
與DLL子產品建立連結也有兩種方法: (1) 隐式連結方式 程式員在建立一個DLL檔案時,連結程式會自動生成一個與之對應的LIB導入檔案。該檔案包含了每一個DLL導出函數的符号名和可選的辨別号,但是并不含有實際的代碼。LIB檔案作為DLL的替代檔案被編譯到應用程式項目中。具體操作方法會在後面提到。 (2) 顯式連結方式(動态加載) 顯式連結方式對于內建化的開發語言(例如VB)比較适合。 說明:在後面的例程中将使用第一種連結方法。 |
4. 應用程式(exe檔案)怎樣找到動态庫? |
(Master)這對于不同的系統版本,其方式不一樣,如在XP、win7、win8系統下都不一樣。例如在XP系統下,應用程式是優先到C:\Windows\System32路徑下去找,完了之後再到對應目錄下去找。 |
動态庫的調用
先不說如何開發動态庫,先來感受一下動态庫是如何被使用的。
Step1:複制所需檔案到指定位置 |
這裡需要三個檔案,socketclient.dll、socketclient.lib、socketclientdll.h,将這三個檔案複制到項目目錄下,如下圖所示。然後再将頭檔案socketclientdll.h添加到工程裡。 |
dll和lib檔案打不開,這裡就隻展示socketclientdll.h檔案了。 |
|
Step2:連結lib檔案 |
右擊工程名→properties,彈出如下對話框, 将socketclient.lib檔案的檔案名複制到圖中所示位置,完了如下圖。 |
Step3:建立源檔案,編寫調用動态庫的代碼。 |
main.c檔案 |
|
上面的例程是已經定義了一套socket用戶端發送封包、接受封包的api接口,并且發送、接收等函數都已經寫好了,封裝在庫檔案中(lib檔案),我們隻需調用即可。那麼這些動态庫庫究竟是如何生成的呢?這些庫檔案(這裡其實就是dll和lib檔案)裡面裝的是什麼呢?這在後面會詳細講到。 |
前面一節是講述如何使用已經建立好的動态庫,這一節則是講述如何開發動态庫。這裡就以實作前一節的動态庫功能為例來講述實際工程開發中是如何實作動态庫的建立與開發的。
動态庫的建立
Step1:建立工程 |
第一步和之前的建立工程一樣,如下圖所示。 接下來的一步和之前略有不同,如下圖所示。 |
Step2:添加頭檔案itcast_comm.h。頭檔案内容如下。 |
|
Step3:建立源檔案MySocketLib.c |
接下來就是在要在檔案MySocketLib.c裡編輯自己的庫函數了。我們就以master給的第一套api接口為例來編寫這些函數的具體源代碼。 這裡先打樁,然後再編寫個動态庫測試程式來看看有木有成功,若成功了則繼續往下編寫動态庫函數。 |
|
一般的函數是像上述這樣定義的,可是動态庫開發不一樣,這裡需要将各個函數的傳回類型用itcast_comm.h頭檔案中的宏定義ITCAST_FUNC_EXPORT(returnType)來替換,完了如下所示。 |
|
Step4:編譯生成動态庫檔案,如下所示。 |
動态庫測試程式的建立
類似動态庫調用那一節,需要添加lib檔案到測試工程的連結器。
Step1:建立測試工程 |
建立一個工程,這個工程是用來測試剛剛開發的動态庫的。注意這時候就是建立一個普通的工程,與建立動态庫開發環境有所不同,不同點如下圖所示。 |
Step2:複制所需檔案到指定位置 |
如“同動态庫的調用”一節所述,這裡也需要三個檔案。 将在動态庫開發中生成的兩個檔案MySocketLib.dll、MySocketLib.lib和socketclientdll.h共三個檔案複制到指定位置,如下圖所示。然後再将頭檔案socketclientdll.h添加到工程裡。 |
Step3:連結lib檔案 |
同樣是右擊工程名→properties,将MySocketLib.lib檔案的檔案名複制到下圖所示位置。 |
Step4:建立源檔案,編寫調用動态庫的代碼。 |
|
Step5:編譯調試 |
在“rv = cltSocketInit(&handle);”處設定斷點,如果能夠成功進入該函數(也就是進入了動态庫),并成功執行該函數裡面的代碼,則說明動态庫調用成功了。 |
編寫動态庫函數
當測試程式成功測試了動态庫的調用後,就說明動态庫已經建立成功了。接下來就是要繼續完善動态庫函數了。
最後動态庫的源代碼如下。 |
|
編譯該動态庫工程即可更新在對應路徑下的動态庫檔案MySocketLib.dll和MySocketLib.lib。 |
動态庫檔案弄好之後,就要測試動态庫中的函數是否可用,那麼就要将新生成的兩個庫檔案拷貝到之前的測試程式路徑下,以替換之前的庫檔案。具體方法在前面已經說過了。 |
将動态庫檔案拷貝後,就要編寫動态庫測試程式了,以便于測試這些動态庫函數是否可用,測試程式如下所示。 |
|
編譯該測試工程後,就可以調試測試動态庫函數是否編寫成功了,如果沒有則還需要到動态庫開發環境中去修改庫函數,然後将新生成的庫檔案拷貝到測試程式路徑下再次測試,這樣直到測試成功為止。 |
添加日志記錄
工程開發中,常常需要将程式的執行狀态記錄下來儲存到一個日志檔案中去,以便于調試。
這裡需要兩個檔案:itcastlog.h和itcastlog.c,哪裡需要用到日志記錄,就将這個兩個檔案複制到哪裡,比如上一節中的動态庫想要用日志來記錄程式執行狀态,就将這兩個檔案複制到動态庫程式目錄下,然後将頭檔案itcastlog.h添加到工程中。 若在MySocketLib.c檔案中想要用日志記錄,那麼還要在MySocketLib.c中包含頭檔案itcastlog.h。 |
itcastlog.h檔案如下 |
|
itcastlog.c |
|
那麼再實踐中是如何使用的呢?其實很簡單,作為示例,下面就展示一下cltSocketInit()函數是如何調用日志顯示的,如下所示。 |
執行完程式後,看C:\itcast目錄下的log檔案,如下圖所示。 |
生成的日志是被放在了C槽根目錄下的itcast檔案夾裡,這可以由itcastlog.c檔案中的ITCAST_Error_OpenFile()函數看出來。注意是要先在C槽根目錄下建立一個檔案名為itcast的檔案夾。 |
第二套API函數實作動态庫開發
前面講述動态庫的開發是基于第一套API函數接口來實作的,接下來要用第二套API函數來實作。
其實基本原理和第一套API函數實作是一樣的,隻不過第二套API的部分函數的接口不一樣,是以導緻了函數内容有些變化。如下所示。 |
|