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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态链接库dll的两种加载方式

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态链接库dll的两种加载方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在第一篇技術博客"動態鏈接庫簡介"中說到了兩種加載方式,當時沒有詳細說明,這里詳細說明一下

可以通過兩種方式

???? 1.隱式鏈接(需要.dll,.lib,.h)

?????? ?2.顯式鏈接(需要.dll,.h)

方法1:隱式鏈接----需要.lib.dll.h文件

?

隱式鏈接就是在程序開始執行時就將DLL文件加載到內存當中,而顯示鏈接,是實時加載,程序需要的時候加載,不需要的時候,卸載。

這種方式需要DLL文件,以及相應的Lib文件和頭文件

?

只要沒有在程序中顯式鏈接的,都是隱式鏈接

?

Windows程序bin目錄包含了可執行文件(.exe)和動態鏈接庫(.dlll),lib目錄包含了靜態庫

步驟

第一步:將.dll,lib,.h文件放入對應的搜索路徑
??????
●其中動態庫的搜索路徑點擊這里查看,記住最重要的兩個
?????????????
1、項目當前目錄(.cpp)目錄
????????????? 2
path環境變量中的目錄

?????? ●靜態庫的搜索路徑包括
????????????? 1
項目當前目錄.cpp目錄(項目和解決方案的Debug不行)(也不是解決方案目錄)
????????????? 2
VC設置中的庫目錄(Library Directories)

注:如果lib庫不放到搜索路徑中,也可以在程序中添加

?????????????#pragmacomment(lib,"D:/DLLTest.lib")//若是相對路徑,則為項目當前.cpp目錄

? ? ? ?頭文件搜索路徑包括
????????????? 1
VC設置中的包含目錄(Include?Directories)

第二步:一定要在VC設置中的依賴項中添加你用到的庫的名字

第一種(對應上面每種搜索路徑1):針對數量較少的庫

設置.dll,.lib搜索路徑:直接將.dll,.lib,.h放入項目當前目錄下(即含有項目源文件.cpp的目錄)

設置.h的搜索路徑:VC設置中的包含目錄(Include?Directories)加入你的.h路徑

然后在鏈接->輸入->附加依賴項中加入你要使用的靜態庫。

這里只添加靜態庫





就可以使用DLL中的函數了。

?

第二種(對應上面每種搜索路徑2):針對數量比較多的庫(Opencv)

Opencv,OSG等開源庫的配置

這種方式也是通常開源庫的配置方式,Opencv,OSG

步驟如下

步驟1.添加DLL的目錄

?????? 方法1dll目錄(通常為bin目錄)放入環境變量Path(需要重啟)path是搜索動態庫的目錄

步驟2.添加靜態庫lib庫目錄和頭文件的目錄

在工程中的VC++目錄中添加靜態庫目錄和頭文件目錄


步驟3.添加靜態庫

在鏈接->輸入->附加依賴項中加入你要使用的靜態庫(當程序中調用時,會在上述配置的庫目錄中尋找這個庫)

這里只添加靜態庫,動態庫的目錄已放入環境變量中,系統會搜索這個路徑的,自動加載.dll

RmwRoadBoundaryStraightLineDLL.lib


然后,在程序中添加頭文件 (在上述配置的頭文件目錄中尋找),就可以使用DLL中的函數了。


方法2:顯式鏈接---需要DLL(不需要.lib,.h文件)

就是顯式加載DLL


注意:顯示鏈接,導出DLL的時候,采用extern “C”的方式,而不采用_declspec(dllexport),因為_declspec(dllexport)會有一個名字改編的問題(采用了_cdecl調用規約的C++編譯方式)

示例:

?

如庫文件對應的頭文件如下

#ifndef DLLTEST_H

#defineDLLTEST_H

?

//該宏完成在dll項目內部使用__declspec(dllexport)導出

//dll項目外部使用時,用__declspec(dllimport)導入

//DLL_EXPORTS.cpp中定義

#ifdefDLL_EXPORTS

#defineDLL_EXPORTS?extern"C"_declspec(dllexport)

#else

#define DLL_EXPORTS?extern"C"_declspec(dllimport)

#endif

//函數聲明

DLL_EXPORTSint ?Add(int a,int b);

DLL_EXPORTSint? Sub(int a,int b);

DLL_EXPORTSint? Divide(int a,int b);

#endif//DLLTEST_H

?

?

測試代碼:

?????? typedefint(*Add)(int a, int b);

??????typedefint(*Sub)(int a, int b);

??????HINSTANCE hDLL;

??????Add Add_;//函數指針

?????? hDLL =LoadLibrary(_T("D:/DLLTest.dll"));//加載動態鏈接庫DLLTest.dll文件;

?????? Add_ = (Add)GetProcAddress(hDLL,"Add");

??????intresult = Add_(5, 8);

?????? printf("5+8:%d\n",result);

?????? FreeLibrary(hDLL);//卸載.dll文件;

?

以下是采用__declspec(dllexport)方式導出,不推薦這種方式需要注意函數名的書寫問題!

現在DLLTest.h中有函數(采用__declspec(dllexport)方式導出)

#ifndef DLLTEST_H

#defineDLLTEST_H

?

//該宏完成在dll項目內部使用__declspec(dllexport)導出

//dll項目外部使用時,用__declspec(dllimport)導入

//DLL_EXPORTS.cpp中定義

#ifdefDLL_EXPORTS

#defineDLL_EXPORTS?__declspec(dllexport)

#else

#define DLL_EXPORTS?__declspec(dllimport)

#endif

?

?

intDLL_EXPORTS Add(int a,int b);

intDLL_EXPORTS Sub(int a,int b);

intDLL_EXPORTS Divide(int a,int b);

?

#endif//DLLTEST_H

?

測試代碼

?????? typedefint(*Add)(int a, int b);

??????typedefint(*Sub)(int a, int b);

??????HINSTANCE hDLL;

??????Add Add_;//函數指針

?????? //也可以采用hDLL =LoadLibrary(_T("D:/DLLTest.dll"));

?????? hDLL =LoadLibraryA(("D:/DLLTest.dll"));//加載動態鏈接庫DLLTest.dll文件;

?

Add_ = (Add)GetProcAddress(hDLL,"?Add@@YAHHH@Z");//!!!!獲取函數地址

??????intresult = Add_(5, 8);

?????? printf("5+8:%d\n",result);

?????? FreeLibrary(hDLL);//卸載.dll文件;

這里需要注意的是:GetProcAddress(hDLL,"函數名");中的函數名要是DLL中的函數名,這個函數名可以用PE Explorer軟件查看

由于采用的是VC++處理函數名方式,所以

GetProcAddress(hDLL,"?Add@@YAHHH@Z");// GetProcAddress(hDLL,"函數名");


而不是簡單的“Add”,因為DLL中的函數名是結果VC++方式處理過的函數名

顯示調用,最好采用extern “C”的方式導出DLL

所以采用隱式鏈接方式的時候,只加載需要的DLL在附加依賴項中,只添加需要的DLL對于的lib,不要多加,否則會造成1.加大程序啟動時間 2.內存浪費


參考文獻

1、《C++ Primer(4特別版)

2、《VC++深入詳解》孫鑫

總結

以上是生活随笔為你收集整理的动态链接库dll的两种加载方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。