轉載:http://www.javashuo.com/article/p-zlzyassm-nr.htmlios
1.dll的特色程序員
代碼複用是提升軟件開發效率的重要途徑。通常而言,只要某部分代碼具備通用性,就可將它構形成相對獨立的功能模塊並在以後的項目中重複使用。比較常見的例子是各類應用程序框架,ATL、MFC等,它們都以源代碼的形式發佈。因爲這種複用是「源碼級別」的,源代碼徹底暴露給了程序員,於是稱之爲「白盒複用」。「白盒複用」的缺點比較多,總結起來有4點。
暴露了源代碼;api
多份拷貝,形成存儲浪費; 框架
容易與程序員的「普通」代碼發生命名衝突; 模塊化
更新功能模塊比較困難,不利於問題的模塊化實現;
實際上,以上4點歸納起來就是「暴露的源代碼」形成「代碼嚴重耦合」。爲了彌補這些不足,就提出了「二進制級別」的代碼複用。使用二進制級別的代碼複用必定程度上隱藏了源代碼,對於緩解代碼耦合現象起到了必定的做用。這樣的複用被稱爲「黑盒複用」。 函數
說明:實現「黑盒複用」的途徑不僅dll一種,靜態連接庫甚至更高級的COM組件都是。spa
2.VS建立新一個空的解決方案(一個解決方案下能夠有不少project).net
2.建立dll3d
文件------>新建------>項目------>Win32控制檯應用程序------>code
選擇dll -- 勾選導出符號 -- 不勾選預編譯頭文件
刪除stdafx.h 、stdafx.cpp、targetver.h、dllmain.cpp,把MyDll.h修改爲dllexport.dll。修改MyDll.cpp中#include "stdafx.h" #include "MyDll.h"改成 "dllexport.h"
若是生產dll和使用dll的工程在一個解決方案中,咱們能夠指定dll輸出目錄
$(SolutionDir) --- 解決方案目錄
$(Platform) ---- 平臺目錄(x86/x64)
$(Configuration) --- 編譯模式(Debug/Release)
由於dll庫是函數的實現,lib裏面是函數的聲明,咱們也指定他的輸出路徑
這是咱們編譯工程:
這時在解決方案目錄下生成bin和lib目錄
3.建立useDll工程
使用dll
導入頭文件 指定導入
在運行以前咱們要指定UseDll工程的exe的輸出目錄
運行結果:
經過配置工程屬性來使用dll庫
工程—屬性—配置屬性—連接器—常規—附加庫目錄:加上lib文件存放目錄。
而後添加工程引用的lib文件名:工程—屬性—配置屬性—連接器—輸入—附加依賴項:加上lib文件名。
顯式調用dll:獲取dll庫的路徑,無需配置環境,沒法進行隱式連接
調用:
#include "stdafx.h" #include <iostream> #include <Windows.h> #include <Shlwapi.h>// 使用PathRemoveFileSpec函數 using namespace std; #pragma comment(lib, "shlwapi.lib") //這個庫也要有,否則會報連接錯誤 typedef int(*MyAdd)(int a,int b); typedef int(*MySub)(int i,int j); int main() { TCHAR ModulePath[MAX_PATH] = { 0 }; GetModuleFileName(NULL,ModulePath,MAX_PATH); ::PathRemoveFileSpec(ModulePath);//C:\\TestDemo\\Debug wstring dllpath = ModulePath; dllpath += L"\\FunDll.dll"; HMODULE hModule = LoadLibrary(dllpath.c_str()); if (hModule) { MyAdd func = (MyAdd)GetProcAddress(hModule, "Add");//顯式調用dll中的Add cout << func(1, 5) << endl; MySub funs = (MySub)GetProcAddress(hModule,"Sub');//顯式調用dll中的Sub cout << funs(5,3) <<endl; } cout << fnMyDll() << endl;//調用dll中的函數 FreeLibrary(hModule); return 0; }