動態鏈接庫鏈接外部的客戶端
在工程名"dll"頭文件,添加:
#ifdef dll_API #else #define dll_API _declspec(dllimport) dll_API int add(int a,int b); dll_API int jianfa(int a,int b);
-----------------------------------------------------------------
在工程名"dll"源文件,添加:
#define dll_API _declspec(dllimport) #include"dll.h" int add(int a,int b) { return a+b; } int jianfa(int a,int b) { return a-b; }
編譯后,把dll.dll和dll.lib復制粘貼給工程名為“dlltest”目錄當中。
----------------------------------------------------------------------
訪問動態鏈接庫的類:
在工程名"dll"頭文件,添加:
#ifdef dll_API #else #define dll_API _declspec(dllimport) dll_API int add(int a,int b); dll_API int jianfa(int a,int b); class dll_API Point { public: void output(int x,int y); };
---------------------------------------------------------
在工程名"dll"源文件,添加:
#define dll_API _declspec(dllimport) #include"dll.h" #include<windows.h> #include<stdio.h> int add(int a,int b) { return a+b; } int jianfa(int a,int b) { return a-b; } void Point::output(int x,int y) {//獲取句柄 HWND hwnd=GetForegroundWindow(); HDC hdc=GetDC(hwnd); char buf[20]; memset(buf,0,20);//將字符數組當中的元素都值為0 sprintf(buf,"x=%d,y=%d",x,y); TextOut(hdc,0,0,buf,strlen(buf)); ReleaseDc(hwnd,hdc); }
GetForegroundWindow函數,可以當前使用的句柄
將編譯生成的dll和lib文件復制粘貼到dlltest文件目錄。
---------------------------------------------------------------
在"dlltest"添加按鈕,其函數內容為:
void CdlltestDlg::OnOutput() { Point pt; pt.output(5,3); }
編譯運行,窗口顯示:
x5,y=3
意味著導出dll的類,還導出了成員函數output。
如果不想導出dll整個類,只是導出指定的成員函數。
-------------------------------------------------------------
在“dll”頭文件當中,修改為:
#ifdef dll_API #else #define dll_API _declspec(dllimport) dll_API int add(int a,int b); dll_API int jianfa(int a,int b); class /*dll_API*/ Point { public: dll_API void output(int x,int y); //dll_API在前面,表示導出這個類的成員函數 //為了證明導出指定函數,我們可以添加一個新的成員函數: void test(); };
--------------------------------------------------------------------
在“dll”源文件當中,實現:
#define dll_API _declspec(dllimport) #include"dll.h" #include<windows.h> #include<stdio.h> int add(int a,int b) { return a+b; } int jianfa(int a,int b) { return a-b; } void Point::output(int x,int y) {//獲取句柄 HWND hwnd=GetForegroundWindow(); HDC hdc=GetDC(hwnd); char buf[20]; memset(buf,0,20);//將字符數組當中的元素都值為0 sprintf(buf,"x=%d,y=%d",x,y); TextOut(hdc,0,0,buf,strlen(buf)); ReleaseDc(hwnd,hdc); } //////////////////////////////////////// void Point::test() { } /////////////////////////////////////
用dumpbin查看一下,查出dll沒有導出test,而導出了指定的成員函數output.
然后把”dll“工程的目錄里面的dll和.lib復制粘貼給工程名為“dlltest”目錄當中。
在“dlltest”工程,編譯一下,運行,結果和導出整個類一樣。
PS:雖然dll中沒有導出類,但是在外部還可以聲明其類的對象,利用對象去調用被導出的成員函數。
如果成員函數是私有的,即使被導出了,還因為訪問權限而不能被調用。
額外知識筆記:
1.如果用c++編譯的動態鏈接庫,導出的成員函數名字會發生變化。當用c語言編寫的客戶端去訪問這個動態鏈接庫
就不能識別出被導出的成員函數,因為名字識別不出來。
2.如果用c++編寫的客戶端就可以訪問c++編寫的被導出的函數,因為改變名字是同一種語言的編譯器可以識別出來。
3.如果換成其他的c++編寫的客戶端也不能訪問被導出的函數。
---------------------------------------------------------
為了解決這個問題,解決辦法是不要讓函數名稱發生改變:
在“dll”頭文件當中,修改為:
#ifdef dll_API #else #define dll_API extern "C"/*此處修改,一定要大寫字母*/ _declspec(dllimport) dll_API int add(int a,int b); dll_API int jianfa(int a,int b); class /*dll_API*/ Point { public: dll_API void output(int x,int y); //dll_API在前面,表示導出這個類的成員函數 //為了證明導出指定函數,我們可以添加一個新的成員函數: void test(); };
--------------------------------------------------
在“dll”源文件當中,實現:
#define dll_API extern "C"/*此處修改,一定要大寫字母*/ _declspec(dllimport) #include"dll.h" #include<windows.h> #include<stdio.h> int add(int a,int b) { return a+b; } int jianfa(int a,int b) { return a-b; } void Point::output(int x,int y) {//獲取句柄 HWND hwnd=GetForegroundWindow(); HDC hdc=GetDC(hwnd); char buf[20]; memset(buf,0,20);//將字符數組當中的元素都值為0 sprintf(buf,"x=%d,y=%d",x,y); TextOut(hdc,0,0,buf,strlen(buf)); ReleaseDc(hwnd,hdc); }
編譯后,在執行dumpbin可以查看函數名字。
extern "C"的缺陷:
不能夠導出類的成員函數,只能導出全局函數,如:
dll_API int add(int a,int b);
dll_API int jianfa(int a,int b);
而不能導出類的成員函數:
class /*dll_API*/ Point { public: dll_API void output(int x,int y); void test(); };
----------------------------------------------------
如果調用約定改變,即使有extern"C",也怒能導出函數。
為了解決這個問題,在“dll”頭文件當中,修改為:
dll_API int _stdcall add(int a,int b);
dll_API int _stdcall jianfa(int a,int b);
使用標準調用約定_stdcall。
-----------------------------------------------------
在“dll”源文件當中,修改:
int _stdcall add(int a,int b) { return a+b; } int _stdcall jianfa(int a,int b) { return a-b; }
編譯后,查看函數名字沒有變化,顯示為:
_add@8
_jianfa@8
8表示被導出函數所占的字節數
------------------------------------------
為解決名字改編問題(利用添加def文件),下篇文章再做筆記。
看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170124/94396.html
文章列表