日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

VC DLL总结

發(fā)布時(shí)間:2025/6/17 c/c++ 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC DLL总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、DLL的導(dǎo)出方法

1、使用_declspec(dllexport) 方法

???? DLL里全是C++的類的話,你無法在DEF里指定導(dǎo)出的函數(shù),只能用__declspec(dllexport)導(dǎo)出類。

extern "C" _declspec(dllexport) int sum(int a,int b);//本文所有的例子只有一個(gè)sum即加法函數(shù)。

???? ? 在制作DLL導(dǎo)出函數(shù)時(shí)由于C++存在函數(shù)重載,因此__declspec(dllexport) function(int,int) 在DLL會(huì)被decorate,例如被decorate成為 function_int_int,而且不同的編譯器decorate的方法不同,造成了在用GetProcAddress取得function地址時(shí)的不便,使用extern "C"時(shí),上述的decorate不會(huì)發(fā)生,因?yàn)镃沒有函數(shù)重載,但如此一來被extern"C"修飾的函數(shù),就不具備重載能力,可以說extern 和 extern "C"不是一回事。

??????? 在VC++中,如果生成DLL可以不使用.def文件。只需要在VC++的函數(shù)定義前要加__declspec(dllexport)修飾就可以了。但是使用__declspec(dllexport)和使用.def文件是有區(qū)別的。如果DLL是提供給VC++用戶使用的,只需要把編譯DLL時(shí)產(chǎn)生的.lib提供給用戶,它可以很輕松地調(diào)用你的DLL。但是如果DLL是供VB、PB、Delphi用戶使用的,那么會(huì)產(chǎn)生一個(gè)小麻煩。因?yàn)閂C++對(duì)于__declspec(dllexport)聲明的函數(shù)會(huì)進(jìn)行名稱轉(zhuǎn)換,如下面的函數(shù):
????__declspec(dllexport) int __stdcall IsWinNT()
????會(huì)轉(zhuǎn)換為IsWinNT@0,這樣你在VB中必須這樣聲明:
????Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long
????@的后面的數(shù)由于參數(shù)類型不同而可能不同。這顯然不太方便。所以如果要想避免這種轉(zhuǎn)換,就要使用.def文件方式。
????EXPORTS后面的數(shù)可以不給,系統(tǒng)會(huì)自動(dòng)分配一個(gè)數(shù)。對(duì)于VB、PB、Delphi用戶,通常使用按名稱進(jìn)行調(diào)用的方式,這個(gè)數(shù)關(guān)系不大,但是對(duì)于使用.lib鏈接的VC程序來說,不是按名稱進(jìn)行調(diào)用,而是按照這個(gè)數(shù)進(jìn)行調(diào)用的,所以最好給出。如:
EXPORTS?
test @1?

?????? 若要導(dǎo)出函數(shù),__declspec(dllexport) 關(guān)鍵字必須出現(xiàn)在調(diào)用約定關(guān)鍵字的左邊(如果指定了關(guān)鍵字)。例如:

 復(fù)制代碼
__declspec(dllexport) void __cdecl Function1(void);

若要導(dǎo)出類中的所有公共數(shù)據(jù)成員和成員函數(shù),關(guān)鍵字必須出現(xiàn)在類名的左邊,如下所示:

 復(fù)制代碼
class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };

2、使用def文件定義導(dǎo)出

?

.def 文件必須至少包含下列模塊定義語句:

?

  • 文件中的第一個(gè)語句必須是 LIBRARY 語句。此語句將 .def 文件標(biāo)識(shí)為屬于 DLL。LIBRARY 語句的后面是 DLL 的名稱。鏈接器將此名稱放到 DLL 的導(dǎo)入庫(kù)中。

  • EXPORTS 語句列出名稱,可能的話還會(huì)列出 DLL 導(dǎo)出函數(shù)的序號(hào)值。通過在函數(shù)名的后面加上 @ 符和一個(gè)數(shù)字,給函數(shù)分配序號(hào)值。當(dāng)指定序號(hào)值時(shí),序號(hào)值的范圍必須是從 1 到 N,其中 N 是 DLL 導(dǎo)出函數(shù)的個(gè)數(shù)。如果希望按序號(hào)導(dǎo)出函數(shù)。

  • .def 文件中的注釋由每個(gè)注釋行開始處的分號(hào) (;) 指定,且注釋不能與語句共享

  • 用def文件還可以改變導(dǎo)出的函數(shù)的名字,例如?? myadd = add? 使得導(dǎo)出的函數(shù)叫myadd,而不是add

二、 dll文件的導(dǎo)入

1. 隱式的加載時(shí)鏈接

VC中加載DLL的LIB文件的方法有以下三種:
????? ①LIB文件直接加入到工程文件列表中
在VC中打開File View一頁,選中工程名,單擊鼠標(biāo)右鍵,然后選中“Add Files to Project”菜單,在彈出的文件對(duì)話框中選中要加入DLL的LIB文件即可。
????? ②設(shè)置工程的 Project Settings來加載DLL的LIB文件
打開工程的 Project Settings菜單,選中Link,然后在Object/library modules下的文本框中輸入DLL的LIB文件。
?????? ③通過程序代碼的方式
加入預(yù)編譯指令#pragma comment (lib,”*.lib”),這種方法優(yōu)點(diǎn)是可以利用條件預(yù)編譯指令鏈接不同版本的LIB文件。因?yàn)?#xff0c;在Debug方式下,產(chǎn)生的LIB文件是Debug版本,如Regd.lib;在Release方式下,產(chǎn)生的LIB文件是Release版本,如Regr.lib。
?????? 當(dāng)應(yīng)用程序?qū)LL的LIB文件加載后,還需要把DLL對(duì)應(yīng)的頭文件(*.h)包含到其中,在這個(gè)頭文件中給出了DLL中定義的函數(shù)原型,然后聲明。

?????? 在創(chuàng)建DllTest.exe文件之前,要先將MyDll.dll和MyDll.lib拷貝到當(dāng)前工程所在的目錄下面,也可以拷貝到windows的System目錄下。如果DLL使用的是def文件,要?jiǎng)h除TestDll.h文件中關(guān)鍵字extern "C"。TestDll.h文件中的關(guān)鍵字Progam commit是要Visual C+的編譯器在link時(shí),鏈接到MyDll.lib文件,當(dāng)然,開發(fā)人員也可以不使用#pragma comment(lib,"MyDll.lib")語句,而直接在工程的Setting->Link頁的Object/Moduls欄填入MyDll.lib既可。
2.顯式鏈接

  顯式鏈接是應(yīng)用程序在執(zhí)行過程中隨時(shí)可以加載DLL文件,也可以隨時(shí)卸載DLL文件,這是隱式鏈接所無法作到的,所以顯式鏈接具有更好的靈活性,對(duì)于解釋性語言更為合適。不過實(shí)現(xiàn)顯式鏈接要麻煩一些。在應(yīng)用程序中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動(dòng)態(tài)鏈接庫(kù)調(diào)進(jìn)來,動(dòng)態(tài)鏈接庫(kù)的文件名即是上述兩個(gè)函數(shù)的參數(shù),此后再用GetProcAddress()獲取想要引入的函數(shù)。自此,你就可以象使用如同在應(yīng)用程序自定義的函數(shù)一樣來調(diào)用此引入函數(shù)了。在應(yīng)用程序退出之前,應(yīng)該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動(dòng)態(tài)鏈接庫(kù)。下面是通過顯式鏈接調(diào)用DLL中的Max函數(shù)的例子。


#include
#include
void main(void)
{
typedef int(*pMax)(int a,int b);
typedef int(*pMin)(int a,int b);
HINSTANCE hDLL;
PMax Max
HDLL=LoadLibrary("MyDll.dll");//加載動(dòng)態(tài)鏈接庫(kù)MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL,"Max");
A=Max(5,8);
Printf("比較的結(jié)果為%d\n",a);
FreeLibrary(hDLL);//卸載MyDll.dll文件;
}

  在上例中使用類型定義關(guān)鍵字typedef,定義指向和DLL中相同的函數(shù)原型指針,然后通過LoadLibray()將DLL加載到當(dāng)前的應(yīng)用程序中并返回當(dāng)前DLL文件的句柄,然后通過GetProcAddress()函數(shù)獲取導(dǎo)入到應(yīng)用程序中的函數(shù)指針,函數(shù)調(diào)用完畢后,使用FreeLibrary()卸載DLL文件。在編譯程序之前,首先要將DLL文件拷貝到工程所在的目錄或Windows系統(tǒng)目錄下。

  使用顯式鏈接應(yīng)用程序編譯時(shí)不需要使用相應(yīng)的Lib文件。另外,使用GetProcAddress()函數(shù)時(shí),可以利用MAKEINTRESOURCE()函數(shù)直接使用DLL中函數(shù)出現(xiàn)的順序號(hào),如將GetProcAddress(hDLL,"Min")改為GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函數(shù)Min()在DLL中的順序號(hào)是2),這樣調(diào)用DLL中的函數(shù)速度很快,但是要記住函數(shù)的使用序號(hào),否則會(huì)發(fā)生錯(cuò)誤。

?顯式調(diào)用的方法很簡(jiǎn)單,調(diào)用LoadLibrary()和GetProcAddress()即可。

HMODULE LoadLibrary(LPCTSTR lpFileName // file name of module);參數(shù)解釋:lpFileName:指定要載入的動(dòng)態(tài)鏈接庫(kù)的名稱。 返回值:如何函數(shù)調(diào)用成功,則返回值是庫(kù)模塊的句柄,否則返回NULL。FARPROC GetProcAddress(HMODULE hModule, // handle to DLL moduleLPCSTR lpProcName // function name ); ? 參數(shù)解釋:hModule:包含此函數(shù)的DLL模塊的句柄。LoadLibrary或者GetModuleHandle函數(shù)可以返回此句柄。 lpProcName:包含函數(shù)名的以NULL結(jié)尾的字符串,或者指定函數(shù)的序數(shù)值。 返回值:如果函數(shù)調(diào)用成功,返回值是DLL中的輸出函數(shù)地址,否則返回NULL。 如下羅列出DLL顯式調(diào)用的流程: (1)使用LoadLibrary()加載指定名稱的DLL。 (2)使用GetProcAddress()獲取指定名稱的函數(shù)地址,并將其轉(zhuǎn)換成函數(shù)類型。 (3)通過函數(shù)地址調(diào)用函數(shù)。 (4)調(diào)用FreeLibrary()函數(shù)卸載DLL。 假設(shè)在DLL中有一導(dǎo)出函數(shù):extern "C" __declspec(dllexport)? int tulip (int a ,int b); 在程序中調(diào)用DLL中的這一函數(shù): //定義一個(gè)函數(shù)指針
?typedef int (? * FUNCTION )(int,int);? ??
int main() { HINSTANCE hLib; hLib = ::LoadLibrary(_T("MyDll.dll")); FUNCTION tulipFunc; //定義一個(gè)函數(shù)指針變量 tulipFunc =(FUNCTION )::GetProcAddress(hLib ,"tulip");? //調(diào)用dll里的函數(shù)
tulipFunc(8,10);
::FreeLibrary(hLib); return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/carekee/articles/2334607.html

總結(jié)

以上是生活随笔為你收集整理的VC DLL总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。