菜鳥學院
使用VS2017創建DLL並鏈接至其他項目中【轉】
時間 2020-12-25
啓動VS2017,點擊菜單欄上的「文件->新建->項目」創建一個新的開發項目;
在彈出的「新建項目窗口」中,選擇左側「Visual C++」列表下的「Windows桌面」,然後選擇右側的項目類型爲「動態鏈接庫(DLL)」,接着設置項目名稱和存儲位置以及解決方案名稱。配置完畢後,點擊「確定按鈕」確定創建動態鏈接庫項目;
該步驟之後,文件夾中生成DLL1文件夾,包含如下內容
項目創建之後,點擊VS2017界面菜單欄上的「生成 > 生成解決方案」編譯新創建的項目代碼,確認是否存在問題(極少會出現問題);
生成解決方案後,會在Debug文件夾中生成如下文件
編譯結束之後,可以在VS2017的輸出窗口中見到編譯成功的輸出信息;
在VS2017開發界面中,右鍵單擊「解決方案」裏面「Dll1」項目下的「頭文件」目錄,在彈出菜單中選擇「添加 > 新建項」;
在彈出的「添加新項」對話框中,選擇「頭文件(.h)」,然後輸入頭文件的名稱「dll1.h」,之後點擊「添加按鈕」確定添加一個名爲「dll1.h」的頭文件;
相應文件中多處dll1.h頭文件
在Windows中,定義在dll中的變量、函數和類,如果希望讓別的程序能夠訪問。必須通過manifest文件指定導出目標(變量、函數或類)或者通過
_declspec(dllimport)
關鍵字指定需要導出的目標,然後在使用dll的程序中通過
_declspec(dllimport)
關鍵字指定導入的目標。在開發中使用
_declspec()
定義導出/導入目標是最方便的做法,因此,可以繼續向「dll1項目」中添加一個頭文件 「export.h」,然後添加自適應導出/導入目標的宏;(圖中第一個應該爲_declspec(dllimport)第二個爲_declspec(dllexport),存在圖中錯誤)
文件中反應出來的是,在如下目錄下生成export.h文件
鼠標選中DLL1項目右鍵「 屬性」,打開Dll1項目的屬性頁窗口;
在彈出的「Dll1屬性頁窗口」中,將配置設置爲」所有配置」,然後選中「C/C++ > 預處理器」,接着在「預處理器定義」右側的屬性值中增加「EXPORT_DLL」。設置完畢後,點擊「確定按鈕」確定屬性設置;
在屬性頁中定義了EXPORT_DLL宏之後,export.h文件中EXPORT_API宏對應的值就變成了__declspec(dllexport),對於Dll1項目而言,只要使用EXPORT_API修飾的對象,都將變成導出目標。相對而言,在引用Dll1的另一項目中,默認是沒有定義EXPORT_DLL宏的,那麼用EXPORT_API修飾的對象,則都是導入目標;
打開 「dll1.h」文件,使用#include包含「export.h」頭文件,然後使用EXPORT_API聲明一個名爲printHello()的DLL導出函數;
打開「Dll1.cpp」,包含「stdio.h」頭文件並寫入printHello()函數的實現;
生成解決方案(F7),可以在輸出窗口中見到所有代碼均編譯成功;
相應的在Debug文件夾下,多處如下幾個文件
右鍵單擊左側列表中「解決方案」,然後在彈出菜單中選擇「添加 > 新建項目」,向解決方案中添加一個新的控制檯項目,用於測試Dll1中導出的printHello()函數是否可以正常訪問;
在彈出的「添加新項目窗口」中,選擇「Windows桌面 > Windows控制檯應用程序」,然後輸入新項目的名稱並點擊「確定按鈕」創建新項目;
相應文件中表現如下
包含文件如下
右鍵單擊「解決方案」列表中新創建的控制檯項目,在彈出菜單中選擇「設置爲啓動項目」,將控制檯項目設置爲啓動項目。這樣,每當運行程序時,啓動的就是這個新創建的控制檯項目(DLL項目是無法獨立運行的);
點擊VS2017界面中的「本地Windows調試器」按鈕,編譯並運行控制檯項目,會發現有一個黑屏幕一閃而過。這是由於控制檯程序在執行完main()函數後,直接退出了(DevCPP中則會自動暫停,防止控制檯直接退出)。
文件中反應如下
爲了讓控制檯程序執行完畢後依然保持開啓狀態,可以打開 ConsoleApplication1.cpp文件,然後包含stdlib.h文件並在main()函數體的return語句之上添加程序暫停語句」system(「pause」);」
寫好代碼之後,再次調試運行程序,可以見到控制出現並暫停。在控制檯窗口中,點任意鍵可以退出控制檯程序;
回到VS2017開發界面,右鍵單擊「解決方案管理器」列表中的控制檯項目,在彈出菜單中選擇「生成依賴項 > 項目依賴項」打開「項目依賴項窗口」;
在彈出的「項目依賴項窗口」中,勾選依賴於「Dll1」,表示控制檯項目ConsoleApplication1依賴Dll1項目。這樣可以保證每次編譯ConsoleApplication1時,編譯器總會自動先編譯Dll1項目,保證Dll1總是最新的。設置完畢後,點擊「確定按鈕」關閉「項目依賴項窗口」;
右鍵單擊VS2017工作區中的「Dll1.cpp選項卡頁」,在彈出菜單中選擇「打開所在的文件夾」;
在打開的Dll1.cpp文件所在的文件夾中,點擊返回按鈕,重新進入到Dll1項目的Debug輸出目錄中。在該目錄中可以見到Dll1項目生成的符號鏈接庫「Dll1.lib」和動態鏈接庫「Dll1.dll」。 如果需要在另一個項目中加載「Dll1.dll」文件,那麼通過鏈接「Dll1.lib」是最簡便的方式(否則就要通過LoadLibrary()及相關函數通過代碼加載動態庫了);
返回VS2017開發界面中,右鍵單擊「解決方案列表」中的ConsoleApplication1,在彈出菜單中,選擇「屬性頁」,打開控制檯項目的屬性頁;
在彈出的ConsoleApplication1屬性頁窗口中,將配置設置爲「所有配置」,然後在左側「配置屬性」列表中,選擇「鏈接器 > 常規」,接着在右側屬性列表中選擇「附加庫目錄」屬性右方的編輯框,在彈出的下拉列表中選擇「編輯」;
在彈出的「附加庫目錄窗口「中,點擊」宏(M) >>「按鈕,展開VS2017的宏列表;
在展開的VS2017宏列表中,搜索「
(
O
u
t
」
即
可
看
到
列
表
中
顯
示
宏
「
(
O
u
t
」
即
可
看
到
列
表
中
顯
示
宏
「
(OutDir)」表示解決方案Dll1的輸出目錄。由於ConsoleApplication1和Dll1項目均位於解決方案Dll1下,因此在默認配置下,這兩個項目的輸出文件均位於該輸出目錄下。只要將$(OutDir)充當靜態庫的查找目錄,就可以方便的找到「Dll1.lib」。記住這個宏名稱後,點擊「宏(M) <<」按鈕隱藏宏列表頁;
返回「附加庫目錄窗口」中,點擊「新建文件夾圖標」,然後在新出現的附加目錄項中填入「$(OutDir)」並點擊」確定按鈕」結束附加庫設置;
附加庫設置完畢後,可以在項目屬性頁中見到「附加庫目錄」屬性右方已經被填入了設置的值;
選擇「ConsoleApplication1屬性頁」左側列表中的「輸入」,然後在右側「附加依賴項」中填入「dll1.lib;」,告訴編譯器需要鏈接dll1.lib,進而加載我們需要的「Dll1.dll」。設置之後,點擊「確定按鈕」關閉屬性頁;
在VS2017工作區中,打開「ConsoleApplication1.cpp」文件,然後在代碼中包含「dll1.h」(注意這裏的相對路徑,目錄起點爲ConsoleApplication1.cpp所在的目錄),之後在main()函數中添加調用printHello()函數的代碼;
生成解決方案(或F7),一切正常時,可以在VS2017輸出窗口中見到編譯成功的輸出信息。如果出錯,則根據提示修改項目配置或代碼後重新生成解決方案,直到成功爲止;
相應文件更新爲
運行ConsoleApplication1程序,在彈出的控制檯界面中可以見到輸出的「Hello」字符串,表示Dll開發成功。Enjoy!