創建編譯庫文件有個好處就是不容易被修改,加密的,方便調用,但是缺點是不容易查看其中的內容,反編譯比較麻煩。下面讓我們使用VC創建編譯自己的庫文件吧。常用的函數,不常更改的,應該放到庫文件里,所以庫文件的意義非比尋常。但為了(這里需要明白C++庫和C++組件(COM組件)、插件、OCX的區別) DLL與COM面試問題 DLL和插件的相關性 插件是使用了某種規則的DLL 給自己的程序添加插件功能dll做插件 DLL插件設計思想 使用DLL作為插件的設計框架 插件開發(Java) 基於插件式的開發框架 插件技術(Android)
dll庫中主要是一個函數,當然還有類和變量這些輔助對象,其主要目的是為了實現某個特定的功能,可以由任意程序調用。這跟靜態庫不同。
dll與lib的區別:lib是在編譯時和可執行程序打包到一起的,外部看不到它的存在,它在exe里面,所以如果丟失了dll它依然可以運行。它是靜態鏈接庫,是目標對象obj的集合。而dll在導出時,有時沒有lib文件,有時有lib文件,而存在的這種lib文件就是導出文件,到出庫。這樣的lib,導入文件,包含DLL導出的函數和變量的符號名,而真正的函數的實現和數據存在於DLL。lib占用內存,dll只用用時才占用內存。
舉個例子:
__declspec(dllexport)
聲明一個導出函數,是說這個函數要從本DLL導出。我要給別人用。一般用於dll中省掉在DEF文件中手工定義導出哪些函數的一個方法。當然,如果你的DLL里全是C++的類的話,你無法在DEF里指定導出的函數,只能用__declspec(dllexport)導出類。
__declspec(dllimport)
聲明一個導入函數,是說這個函數是從別的DLL導入。我要用。一般用於使用某個dll的exe中不使用__declspec(dllimport)也能正確編譯代碼,但使用__declspec(dllimport)使編譯器可以生成更好的代碼。編譯器之所以能夠生成更好的代碼,是因為它可以確定函數是否存在於DLL中,這使得編譯器可以生成跳過間接尋址級別的代碼,而這些代碼通常會出現在跨DLL邊界的函數調用中。但是,必須使用__declspec(dllimport)才能導入DLL中使用的變量。
為什么叫導入文件,就是把Dll中導出的函數,類給導入到我們自己的應用程序中使用。
使用方法:1、靜態鏈接庫(lib),我們使用隱式鏈接; 2、動態鏈接庫(DLL),不包含lib導入文件,我們用顯式鏈接。但是這樣會很麻煩,我不喜歡這樣用,我會想盡方法讓它帶有lib文件。 3、動態鏈接庫(DLL),包含lib導入文件,我們使用 隱式鏈接。
1. 新建-->項目-->Win32 Console-->勾選dll-->確定。
2. MyDll.h頭文件聲明
#ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) //定義MYDLL_API為導出類型 #else #define MYDLL_API __declspec(dllimport) #endif // This class is exported from the MyDll.dll 該類從MyDll.dll中導出 class MYDLL_API CMyDll { public: CMyDll(void); CMyDll(int _age, char *_name); //年齡和姓名 構造函數 ~CMyDll(); // TODO: add your methods here. void Introduce(); //介紹函數 static void SayStatic(); private: int age; char* name; static int a; };
extern MYDLL_API int nMyDll;//導出全局變量的聲明
extern MYDLL_API float f;
extern MYDLL_API int a;
MYDLL_API int fnMyDll(void); //導出全局函數的聲明
MYDLL_API void SayHell();
3. MyDll.cpp文件的函數和類的實現
#include "stdafx.h" #include "MyDll.h" #include <iostream> #include <string.h> #include <algorithm> using namespace std; // This is an example of an exported variable MYDLL_API int nMyDll=0; MYDLL_API float f = 3.14; MYDLL_API int a = 23; int CMyDll::a = 90; //全局變量 // This is an example of an exported function. MYDLL_API int fnMyDll(void) { return 42; } MYDLL_API void SayHell() //全局函數 { cout<<"Hello World!"<<endl; } //靜態函數 void CMyDll::SayStatic() { cout<<"我是類中的靜態函數"<<endl; cout<<"類中靜態變量初始化值是:a="<<CMyDll::a<<endl; } // This is the constructor of a class that has been exported.這是已導出類的構造函數 // see MyDll.h for the class definition有關該類的定義參閱MyDll.h CMyDll::CMyDll():name(NULL) { return; } CMyDll::~CMyDll() { if(name != NULL) { delete[]name; } } CMyDll::CMyDll(int _age, char *_name):age(0), name(NULL) { this->age = _age; if(_name != NULL) { int len = strlen(_name)+1; if(name==NULL) { name = new char[len]; } strcpy_s(name, len, _name); } } void CMyDll::Introduce() { cout<<"My name is yujianhui"<<endl; cout<<"Name:"<<name<<endl; cout<<"Age:"<<age<<endl; }
項目生成如下:
測試:(這里屬於靜態加載,即lib和dll都存在的情況下)
步驟:1.在程序中添加頭文件;2.加載lib;3.使用。
示例:
#include<iostream> #include "MyDll.h" #pragma comment(lib, "MyDll") using namespace std; int main() { cout<<a<<endl; cout<<f<<endl; SayHell(); CMyDll mydll(24, "yujianhui"); mydll.Introduce(); CMyDll::SayStatic(); system("pause"); }
程序下載:http://pan.baidu.com/s/1mhEqfxQ
程序介紹:VS2010版 使用方法:解壓后,使用VS打開.sln文件,然后單擊Debug->Start Without Debugging就可以看到運行結果了。因為我為了讓壓縮包變小所以刪除了過程文件,會提示你重新編譯,單擊確定即可。