dll的優點
代碼復用是提高軟件開發效率的重要途徑。只要某部分代碼具有通用性,就可將它構造成相對獨立的功能模塊並在之后的項目中重復使用。比較常見的例子是各種應用程序框架,ATL、MFC等,它們都以源代碼的形式發布。由於這種復用是“源碼級別”的,源代碼完全暴露給了程序員,因而稱之為“白盒復用”。
“白盒復用”的缺點有:暴露了源代碼;多份拷貝,造成存儲浪費; 容易與程序員的“普通”代碼發生命名沖突; 更新功能模塊比較困難,不利於問題的模塊化實現;
以上4點概括起來就是“暴露的源代碼”造成“代碼嚴重耦合”。為了彌補這些不足,就提出了“二進制級別”的代碼復用。使用二進制級別的代碼復用一定程度上隱藏了源代碼,對於緩解代碼耦合現象起到了一定的作用。這樣的復用被稱為“黑盒復用”。 說明:實現“黑盒復用”的途徑不只dll一種,靜態鏈接庫甚至更高級的COM組件都是。
對比而言,使用DLL主要有以下優點:使用較少的資源;當多個程序使用同一函數庫時,DLL可以減少在磁盤和物理內存中加載的代碼的重復量。這不僅可以大大影響在前台運行的程序,而且可以大大影響其它在Windows操作系統上運行的程序;推廣模塊式體系結構;簡化部署與安裝。
在http://blog.csdn.net/piaoxuezhong/article/details/61201785中介紹了.DLL文件的顯式調用方法,這篇介紹dll文件的生成方法~
---------------------方式一:只生成dll文件-------------------
首先打開VS2013,新建—項目—Win32控制台應用程序(項目名稱:dllTest)---控制台應用程序—空項目---完成
新建一個源文件source.cpp
1 extern "C" _declspec(dllexport) void myFun(); 2 3 #include "iostream" 4 using namespace std; 5 void myFun() 6 { 7 cout<<"Hello,Jasen_Fu"<<endl; 8 } 9 int main() 10 { 11 myFun(); 12 return 0; 13 }
用控制台exe配置類型自己定義函數,並通過主函數調試, 然后可以通過項目——屬性——配置屬性——常規——項目默認值——配置類型下, 選擇動態庫(.dll)選項 然后點擊生成---生成解決方案,會在工程的Debug目錄下生成一個DLL文件(dllTest.dll)
然后就可以按照之前(http://blog.csdn.net/piaoxuezhong/article/details/61201785)的方法顯式調用生成的dll文件了。
注釋:http://www.cppblog.com/Dutyboy/archive/2010/11/15/133699.html
使用 _declspec(dllexport) 關鍵字從 DLL 導出數據、函數、類或類成員函數。_declspec(dllexport) 會將導出指令添加到對象文件中,不需要使用 .def 文件。extern "C"的真實目的是實現類C和C++的混合編程。在C++源文件中的語句前面加上extern "C",表明它按照類C的編譯和連接規約來編譯和連接,而不是C++的編譯的連接規約。這樣在類C的代碼中就可以調用C++的函數或變量。
使用extern "C" __declspec(dllexport)聲明導出函數,在DLL中的函數名字保持與導出函數名一致。使用__declspec(dllexport)聲明導出函數,在DLL中的函數名字與導出函數名字不一致,有變化。這些差異主要是使用C方式函數C++方式編譯導致的。在使用GetProcAddress( HMODULE hModule, LPCWSTR lpProcName)函數查找導出函數時,最好在DLL中用extern "C" __declspec(dllexport)聲明導出函數。
---------------------方式二:生成lib文件-------------------
先建立一個控制台工程(新建->工程->控制台程序),添加sub.cpp以及add.h文件。
1 //sub.h 2 #ifndef _SUB_H 3 #define _SUB_H 4 void sub(int a,int b); 5 #endif
1 //sub.cpp 2 #include "sub.h" 3 #include <iostream> 4 5 void sub(int a,int b) 6 { 7 std::cout<<"差值為:"<<(a-b)<<std::endl; 8 }
右鍵點擊工程,並選擇工程屬性,選擇靜態鏈接庫(或是一開始新建項目時選擇靜態庫),然后點擊生成--生成解決方案,此時Debug目錄下生成.lib文件。
使用靜態庫
需要.h文件,lib文件,可以把.h和.lib文件拷貝到新建需要調用項目目錄下: (1)設置項目屬性--vc++目錄--庫目錄為lib所在的路徑 (2)將lib添加到項目屬性--鏈接器--輸入--附加依賴項(或者直接在源代碼中加入#pragma comment(lib, “**.lib”)) (3)在頭文件中添加.h頭文件
1 #include <iostream> 2 #include "sub.h" //鏈接庫的頭文件 3 using namespaces std; 4 5 #pragma comment(lib,"sub.lib") //加入鏈接庫 6 7 int main() 8 { 9 sub(10,5); 10 return 0; 11 }
附錄:靜態庫(靜態鏈接庫)、動態庫(動態鏈接庫)的概念
靜態庫:在鏈接步驟中,連接器將從庫文件取得所需的代碼,復制到生成的可執行文件中,這種庫稱為靜態庫,其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗余拷貝。即靜態庫中的指令都全部被直接包含在最終生成的 EXE 文件中了。在vs中新建生成靜態庫的工程,編譯生成成功后,只產生一個.lib文件 動態庫:動態鏈接庫是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。在vs中新建生成動態庫的工程,編譯成功后,產生一個.lib文件和一個.dll文件 靜態庫和動態庫中的lib的區別:http://blog.csdn.net/langb2014/article/details/48392919 靜態庫中的lib:該LIB包含函數代碼本身(即包括函數的索引,也包括實現),在編譯時直接將代碼加入程序當中。 動態庫中的lib:該LIB包含了函數所在的DLL文件和文件中函數位置的信息(索引),函數實現代碼由運行時加載在進程空間中的DLL提供。 總之,lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。
參考:
http://blog.csdn.net/langb2014/article/details/48392919
http://www.cnblogs.com/mypsq/p/5060049.html
http://www.jianshu.com/p/5d2eeeb93590
http://www.itnose.net/detail/6688109.html
http://blog.csdn.net/xiamentingtao/article/details/51055438
http://www.cnblogs.com/houkai/archive/2013/06/05/3119513.html
http://www.jellythink.com/archives/111
http://www.cnblogs.com/TenosDoIt/p/3203137.html (lib)
http://www.tuicool.com/articles/jEvYjm