亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

鏈接庫動態(tài)鏈接庫詳細說明

2020-02-24 14:37:52
字體:
供稿:網(wǎng)友

windows中,鏈接庫分為兩種類型:靜態(tài)鏈接庫.lib和動態(tài)鏈接庫.dll。其中動態(tài)鏈接庫在被使用的時候,通常還提供一個.lib,稱為引入庫,它主要提供被Dll導(dǎo)出的函數(shù)和符號名稱,使得鏈接的時候能夠找到dll中對應(yīng)的函數(shù)映射。
靜態(tài)鏈接庫和動態(tài)鏈接庫的作用相似,都是提供給其他程序進行調(diào)用的資源。其中,動態(tài)鏈接庫的調(diào)用方法分隱式調(diào)用(靜態(tài)導(dǎo)入調(diào)用)和顯示調(diào)用(動態(tài)導(dǎo)入調(diào)用)。?

編譯環(huán)境
Microsoft Visual Stdio 2010
--------------------------------------------------------------------------------
DLL導(dǎo)出符號
例,首先生成一個dll1.dll和dll1.lib


// DLL1工程,dll1.cpp
// _declspec(dllexport)為導(dǎo)出符號
_declspec(dllexport) int add(int a, int b)
{
return a + b;
}


利用微軟的depends工具查看dll1.dll,導(dǎo)出的符號如下:
http://www.cnblogs.com/monotone/?
其中各字段意義:Ordinal(符號序號,后面使用GetProcAddress的時候,參考的數(shù)值),Hint(這個我也不是太明白,據(jù)說是不用了解),F(xiàn)unction(這個就是函數(shù)導(dǎo)出后的符號名稱了),EntryPoint(這個是函數(shù)在DLL中的地址)。
這里之所以函數(shù)的名稱變成了這樣子,是因為使用的編譯器默認(rèn)使用C++方式進行編譯,由于C++支持重載,那么需要給函數(shù)名增加額外的符號,來使與同名的重載函數(shù)區(qū)分開來,才能在DLL中通過符號名來進行定位。
這里可以做個簡單的測試,新建控制臺測試工程DllTest如下。

?

?


// DllTest工程,DllTest.cpp
#include
using namespace std;
int main(void)
{
// extern int add(int a, int b);
// _declspec(dllimport)是導(dǎo)入聲明,這種方式比上面的方式更有效,同時編譯器能邊編譯出更加高效的代碼。
_declspec(dllimport) int add(int a, int b);
cout getchar();
return 0;
}


編譯鏈接,提示鏈接錯誤 error LNK2019: unresolved external symbol "__declspec(dllimport) int cdecl add(int,int)" (__imp_?add@@YAHHH@Z) referenced in function _main,很明顯的編譯器在編譯的時候,把add函數(shù)也給重命名了,并且和上面用depends查看的一樣。意思是沒有找到這個符號的定義。

添加代碼后如下:(注意,我這里兩個工程的輸出目錄都是在和解決方案同目錄的debug下,為了避免每次修改都重新拷貝lib文件,直接使用相對路徑聲明。)

?

?


// DllTest工程,DllTest.cpp
#include
using namespace std;
#pragma comment(lib, "../debug/dll1.lib") // 顯示的聲明要鏈接dll1.lib,隱式調(diào)用
int main(void)
{
// extern int add(int a, int b);
// _declspec(dllimport)是導(dǎo)入聲明,這種方式比上面的方式更有效,同時編譯器能邊編譯出更加高效的代碼。
_declspec(dllimport) int add(int a, int b);
cout getchar();
return 0;
}


編譯運行后,使用depends工具對DllTest.exe查看其依賴的輸入信息如下:
image?
可以看出,DllTest.exe通過dll1.lib,引入了對dll1.dll的依賴。

--------------------------------------------------------------------------------

DLL提供的頭文件
通常情況下,當(dāng)?shù)玫揭粋€.dll的時候,我們無法得知其提供了哪些函數(shù)調(diào)用(準(zhǔn)確來說,應(yīng)該是調(diào)用方式。因為我們可以利用depends工具查看dll導(dǎo)出的函數(shù)及其序號,當(dāng)然也許可能有其他的方式去知道具體怎么使用,但是肯定無法得知內(nèi)部具體實現(xiàn)細節(jié)。),因此為了方便被使用,通常會提供一個對應(yīng)該dll的.h文件,來聲明其提供給客戶端使用的方式和說明等信息??蛻舳耸褂迷擃^文件對所使用的接口進行導(dǎo)入。但是為了避免很多地方都出現(xiàn)這些函數(shù)的聲明,通常在客戶端直接在.h文件中對所有接口進行導(dǎo)入,而在Dll編譯時,則作為導(dǎo)出使用。方法如下:

?

?


// DLL1工程,dll1.h
#ifndef DLL1_API
#define DLL1_API _declspec(dllimport)
#endif
// 以上代碼表示,如果在包含該頭文件之前,沒有定義DLL1_API宏,那么后面所有DLL1_API宏都展開為_declspec(dllimport),即導(dǎo)入。
// 因為通常情況下客戶端不會去定義這個宏(當(dāng)然,假設(shè)這個宏不會被客戶端中其他文件定義),所以客戶端使用該頭文件的時候,都是用于導(dǎo)入。
DLL1_API int add(int a, int b);

?

?


// DLL1工程,dll1.cpp
#define DLL1_API _declspec(dllexport)
// 注意上面這行,在頭文件被包含前,先定義了DLL1_API這個宏,使得頭文件中DLL1_API都被展開為_declspec(dllexport)了,從而聲明函數(shù)作為導(dǎo)出。
#include "dll1.h"
// 在頭文件中進行了導(dǎo)出聲明的函數(shù),就不用再聲明導(dǎo)出了。
int add(int a, int b)
{
return a + b;
}


相應(yīng)的,TestDll工程中包含.h文件后,也不用再去申明了。

?

?


// DllTest工程,DllTest.cpp
#include
using namespace std;
#include "../dll1/dll1.h" // 包含該頭文件之后,后面就不需要再申明了
#pragma comment(lib, "../debug/dll1.lib") // 顯示的聲明要鏈接dll1.lib,隱式調(diào)用
int main(void)
{
cout getchar();
return 0;
}


以上基本解釋了為什么通常引用dll的時候都有一個頭文件,并且頭文件內(nèi)有很多#ifndef之類的東東了。

--------------------------------------------------------------------------------
動態(tài)鏈接庫導(dǎo)出類
當(dāng)然,動態(tài)鏈接庫也能導(dǎo)出類,要注意的是聲明的方式為class DLL1_API CSample,而不是DLL1_API class CSample。
同時,要注意導(dǎo)出類的同時,其所有成員函數(shù)也已經(jīng)導(dǎo)出,但是仍然遵循類成員變量訪問權(quán)限限制。
如果單獨導(dǎo)出類的成員函數(shù)(聲明方式和全局函數(shù)一樣),那么在客戶端可以實例化類對象,并調(diào)用導(dǎo)出的成員函數(shù),不能調(diào)用沒導(dǎo)出的成員函數(shù)(即使是public的)。

--------------------------------------------------------------------------------
改編了的符號名
在導(dǎo)出符號時,講過C++會對函數(shù)名進行改編,以支持函數(shù)重載。那么就會存在一個問題,如果使用不用的C++編譯器(導(dǎo)致編譯出的符號名不同)或者客戶端使用C編譯器調(diào)用,就會出現(xiàn)LNK2019這樣的鏈接錯誤,找不到符號。這個問題很大的限制了DLL的使用范圍。
解決方法1:
使用extern “C”(注意這個C一定要大寫)前置申明,表明函數(shù)是以C的方式編譯鏈接的。C方式編譯連接導(dǎo)出的函數(shù)不會改編符號名,因而可以避免上述問題。

?

?


// DLL1工程,dll1.h
#ifndef DLL1_API
#define DLL1_API extern "C" _declspec(dllimport)
#endif
// 以上代碼表示,如果在包含該頭文件之前,沒有定義DLL1_API宏,那么后面所有DLL1_API宏都展開為_declspec(dllimport),即導(dǎo)入。
// 因為通常情況下客戶端不會去定義這個宏(當(dāng)然,假設(shè)這個宏不會被客戶端中其他文件定義),所以客戶端使用該頭文件的時候,都是用于導(dǎo)入。
DLL1_API int add(int a, int b);
//class CSample
//{
//public:
// DLL1_API int substract(int a,int b);// 這種情況下,導(dǎo)出類成員函數(shù),編譯不能通過的
//};


這里要注意.h和.cpp中都要加上extern “C”,使得導(dǎo)入和導(dǎo)出都用C編譯方式。

?

?


// DLL1工程,dll1.cpp
#define DLL1_API extern "C" _declspec(dllexport)
// 注意上面這行,在頭文件被包含前,先定義了DLL1_API這個宏,使得頭文件中DLL1_API都被展開為_declspec(dllexport)了,從而聲明函數(shù)作為導(dǎo)出。
#include "dll1.h"
// 在頭文件中進行了導(dǎo)出聲明的函數(shù),就不用再聲明導(dǎo)出了。
int add(int a, int b)
{
return a + b;
}
//
//int CSample::substract(int a,int b)
//{
// return a - b;
//}


然后用depends進行查看:
image?
導(dǎo)出的函數(shù)符號名和函數(shù)聲明時一樣了。由于客戶端使用的時候,導(dǎo)入也是用的extern “C”方式,因此客戶端在編譯鏈接的時候,也使用的是函數(shù)原名稱符號。
顯示,由于使用的是C編譯鏈接方式,C++的類和成員函數(shù)的導(dǎo)出就不能用這種方式了。
此外,如果我們在給函數(shù)聲明加上標(biāo)準(zhǔn)調(diào)用約定:DLL1_API int _stdcall add(int a, int b);(注意,在函數(shù)的定義中也要加上_stdcall)。那么編譯出來的結(jié)果使用depends查看符號名為_add@8,也就是說符號名稱又改了。
解決方法2:
使用模塊定義文件.def,這種文件的格式規(guī)范查看MSDN,搜索.def即可。其中LIBRARY命令用于指名該def文件用于導(dǎo)出庫文件,EXPORTS用于指名導(dǎo)出函數(shù)符號名。也就是說,.def文件主要就用于控制導(dǎo)出符號等信息。

?

?


LIBRARY dll1
EXPORTS
add11=add


我這里給add函數(shù)別名為add11,注意同時需要在.h文件中聲明add為add11(作用就是提供給客戶端使用,當(dāng)然其實也可以直接在客戶端聲明函數(shù)為add11,前提是你知道該函數(shù)的定義方式等)。一旦提供了.def之后,.cpp中提供的任何調(diào)用約定都不再生效,因為.def指定了生成的符號名了。這里只要明白,.def控制了Dll的導(dǎo)出符號,客戶端使用的時候,只要提供了聲明,并且鏈接上.lib文件,就能夠使用了。
補充一句:VC6.0以后的IDE都需要在鏈接選項(LINK)的input-》module define file中,指明.def文件,編譯器才會去使用這個.def文件。

備注:
這一塊關(guān)于調(diào)用約定,以及加不加extern “C”,目前我還比較混亂。等了解了之后,再來這里進行補充,歡迎看客給我提供有關(guān)這一塊比較好的介紹資料。

--------------------------------------------------------------------------------
顯示鏈接(動態(tài)導(dǎo)入鏈接)
前面有提到讓導(dǎo)出的函數(shù)沒有名字,那么客戶端如何對其進行調(diào)用呢。就是使用符號表中的ordinal了(可以通過工具進行查看),當(dāng)然也可以使用函數(shù)名進行導(dǎo)入。動態(tài)導(dǎo)入不需要lib文件和.h文件(如果知道函數(shù)名的話)。

?

?


// DllTest工程,DllTest.cpp
#include
using namespace std;
#include
int main(void)
{
HMODULE hModule = ::LoadLibraryA("dll1.dll");
if(NULL != hModule)
{
typedef int (*ADDPROC)(int a, int b);
//ADDPROC add = (ADDPROC)::GetProcAddress(hModule, "add11"); // 通過函數(shù)名導(dǎo)入
ADDPROC add = (ADDPROC)::GetProcAddress(hModule, MAKEINTRESOURCEA(1)); // 通過ordinal導(dǎo)入,注意第二個參數(shù)此時數(shù)值要放在低字節(jié)位置,具體參見MSDN說明。
if(NULL != add)
cout ::FreeLibrary(hModule);
}
getchar();
return 0;
}


值得一提的是,根據(jù)函數(shù)名稱進行動態(tài)導(dǎo)入的時候,實際上也是根據(jù)符號名的,也就是說,dll提供的符號名要和提供給用戶的函數(shù)聲明一致。

此外,動態(tài)導(dǎo)入動態(tài)鏈接庫時,.exe時無法查看到需要的輸入信息的。

--------------------------------------------------------------------------------
后記
第一次寫這么詳細和這么長的博文,可以看出來寫到后面的時候已經(jīng)越來越粗糙了。因為寫到后來的時候,自己都已經(jīng)不知道要寫什么了,因為如果再擴展下去,需要增加的東西就太多了。同時也有一部分原因是后面的內(nèi)容我理解的不是太透徹,同時使用的也很少??傊@會我腦子已經(jīng)相當(dāng)混亂了。在這里對那些寫博客的大俠們表示深深的敬佩。
以上就是鏈接庫動態(tài)鏈接庫詳細說明的介紹,希望小編整理的相關(guān)知識和資料都對你們有所幫助,更多內(nèi)容請繼續(xù)關(guān)注武林技術(shù)頻道網(wǎng)站!

?

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

久久se这里有精品| 8x福利精品第一导航| jizz18日本| 欧美性三三影院| 国产成人亚洲精品无码h在线| 国产亚洲精品码| 美女激情福利视频在线观看| 欧美极度另类videos高清| 91丨九色丨蝌蚪丨老板| 久久久人成影片一区二区三区| 日本一区二区三区中文字幕| 日韩成人动漫| 中文字幕视频在线| 日本免费看黄色| 亚洲国产一区二区三区在线观看| 欧美美乳视频网站在线观看| 国产精品剧情一区二区在线观看| 午夜精品影院在线观看| 一本大道久久a久久精品综合| 99精品在线视频观看| 97色在线视频观看| 精品亚洲国内自在自线福利| 自拍亚洲欧美老师丝袜| 国产成都精品91一区二区三| 日本一二区不卡| 午夜精品久久久久久久爽| 日本午夜精品理论片a级appf发布| 男同互操gay射视频在线看| 色悠久久久久综合欧美99| 国产又粗又猛又爽又黄91| 老司机成人免费视频| 欧洲精品视频在线| 亚洲一区二区少妇| 97人妻精品一区二区三区免费| 国产suv精品一区二区883| 美女在线观看www| 欧美成人久久| 国产精品人成在线观看免费| 国产精品伦一区| 欧美黄色高清视频| 中文字幕一区二区三区精华液| www日韩欧美| 又粗又大的机巴好爽欧美| 日韩中文字在线| 国产成人精品免费在线| 老司机深夜福利在线观看| 色哟哟视频在线| 欧美一级黄色录像| h1515四虎成人| 国产一区二区三区小说| 国产精品自拍偷拍视频| 亚洲不卡1卡2卡三卡2021麻豆| 91免费视频国产| 成人在线免费看片| 色综合久久久无码中文字幕波多| 91老司机福利 在线| 欧美三区不卡| 久久精品国产一区二区三区肥胖| 国内精品久久久久国产盗摄免费观看完整版| 欧美精彩视频一区二区三区| 91片黄在线观看喷潮| 国产精品久久久久久久久免费樱桃| 自拍偷拍 国产| 激情一区二区三区| 天堂av.com| 91热这里只有精品| 日韩成人精品视频在线观看| 99久久人爽人人添人人澡| 亚洲影视九九影院在线观看| 美女久久久久久久久久久| 羞羞色国产精品网站| 色综合天天综合给合国产| 国产aⅴ精品一区二区三区黄| 亚洲欧美精品日韩欧美| 91国产在线精品| 国产精品亚洲第一区在线暖暖韩国| 美洲天堂一区二卡三卡四卡视频| 免费看的国产视频网站| 国产精品第二页| 国产一级精品在线| 久久九九热免费视频| 九色91偷拍| 国产一区二区三区成人欧美日韩在线观看| 日韩一级av毛片| 精品少妇一区二区三区视频免付费| 久久精品国产亚洲AV无码男同| 男人操女人在线观看| 中国成人在线视频| 中文字幕日韩一区二区三区不卡| 欧美丰满熟妇xxxxx| 久久日韩粉嫩一区二区三区| jizzjizzjizzjizzjizzjizzjizz| 91在线短视频| 亚洲国产成人久久综合一区| 99re在线播放| 伊人22222| 日韩精品国产精品| 两个人hd高清在线观看| 国精产品一区一区三区免费视频| 欧美日韩在线亚洲一区蜜芽| 亚洲精品一区二区三区蜜桃| 一级毛片免费高清中文字幕久久网| 一卡二卡三卡四卡五卡| 忘忧草在线日韩www影院| 看黄色一级大片| 欧美亚洲动漫制服丝袜| 久久亚洲国产精品日日av夜夜| 懂色av一区二区三区在线播放| 精品国产免费视频| 日本最黄视频| 欧美黄污视频| 色一情一乱一区二区三区| 9国产精品视频| 成人在线视频观看| 伊人色综合一区二区三区影院视频| 亚洲乱码日产精品bd在线观看| 国产精品视频500部| 欧美日韩在线第一页| 久久午夜宅男免费网站| 在线看的你懂得| 成人午夜黄色影院| 亚洲精品国产视频| 一区二区三区不卡在线观看| 毛片不卡一区二区| 欧美另类在线视频| 无码日韩精品一区二区免费| 欧美大黑bbbbbbbbb在线| 99精品视频免费观看| 高清国产午夜精品久久久久久| 中文字幕在线免费视频| 亚洲精品性视频| 国产高清视频免费| 韩国18福利视频免费观看| 国产伦精品一区二区三区88av| 免费观看欧美大片| 99精品免费观看| 欧美性色黄在线视频| 小日子的在线观看免费第8集| 97精品国产91久久久久久| 91在线观看免费高清| 亚洲丝袜av一区| 视频精品国内| 一区二区三区四区av| 变态黄色小视频网站| 亚洲人性生活视频| 日本三级福利片| 一区二区在线观看免费视频| 欧美黑人巨大videos精品| 欧美成人精精品一区二区频| 91精品国产综合久久久蜜臀粉嫩| 国产精品老熟女视频一区二区| 97人摸人人澡人人人超一碰| 欧美精品在线第一页| 亚洲一区www| 日韩欧美高清在线视频| 男人天堂av在线播放| 国产偷倩在线播放| 800av在线免费观看| 中文字幕在线观看不卡| av激情成人网| 91亚洲一区| 日本欧美色图| 琪琪第一精品导航| 小草在线视频免费播放| 好吊视频在线观看| 深爱激情久久| 国产精品五区| 午夜视频免费在线| 日本中文字幕一区二区有码在线| 精品影片一区二区入口| 精品久久久久久久久久久久久久久久久久| 国产精品xxx| 美女精品久久久| 午夜精品久久久久| 亚洲欧美在线免费| 综合免费一区二区三区| 亚洲永久一区二区三区在线| 日韩欧美伦理| 日韩av电影免费播放| y97精品国产97久久久久久| a级毛片免费观看在线| 国产精品视频一区二区免费不卡| 国产一二三区在线播放| 亚洲第一免费看片| 麻豆视频在线观看免费网站黄| av在线不卡一区| 丁香花视频在线观看| 尤物视频网站| 国产精品伦子伦| 先锋资源中文在线| 番号集在线观看| 欧美性资源免费| 26uuu成人网一区二区三区| 国产av人人夜夜澡人人爽麻豆| 久久精视频免费在线久久完整在线看| 亚洲mv大片欧洲mv大片| 97夜夜澡人人双人人人喊| 蜜桃传媒入口| 午夜影院在线观看国产主播| 俺来也官网欧美久久精品| 亚洲视频每日更新| 波多野结衣免费观看| 精品国产91久久久久久| 91视频播放| 国产精品丝袜久久久久久不卡| 午夜av免费在线观看| 翔田千里精品久久一区二| 久久久久久久久国产精品| 久久天堂成人| 911精品国产一区二区在线| 天堂电影院在线| 人人精品亚洲| 四虎影院观看视频在线观看| 色婷婷综合缴情免费观看| 九九九九精品九九九九| 人妻av一区二区| 美女的胸无遮挡在线观看| 少妇一区二区三区四区| 欧美91在线| 欧美人一级淫片a免费播放| 日韩电影免费在线观看网站| 国产人成精品一区二区三| 欧美性猛交xxxxxx富婆| 欧美做受高潮电影o| 黄色一级大片在线免费观看| 婷婷丁香一区二区三区| 久久人人爽爽人人爽人人片av| 国产精品久久久久久久久久久久久久久久久久| 成人欧美一区二区三区黑人麻豆| 中文岛国精品亚洲一区| eeuss影院第1页在线| 亚洲国产精彩视频| 久久精品国产久精国产爱| 亚洲精品一卡二卡三卡四卡| 免费黄色av电影| 日韩中文在线视频| 一区二区的视频| 怡红院怡春院首页| 亚洲国产高清在线| 99久久精品国产一区二区三区| 日韩欧美一级在线播放| 免费成人在线视频观看| 精品国产18久久久久久| 在线观看日韩一区| 91久色国产| 成人午夜激情视频| 亚洲国产欧美国产综合一区| 久久国产手机看片| av在线不卡播放| 亚洲免费成人av在线| 亚洲欧洲日韩精品| 污视频在线看操| 一级片在线播放| 日韩美脚连裤袜丝袜在线| 欧美日韩日日夜夜| 日韩美女网站| 日韩视频一区二区| 成人免费xxxxx在线视频| 日韩精品成人一区二区在线观看| 精品一区二区成人精品| 免费在线播放第一区高清av| 亚欧日韩另类中文欧美| 欧美系列在线观看| 99国产高清| 久久久www成人免费精品张筱雨| 成人久久久精品乱码一区二区三区| 中文字幕亚洲精品一区| 97成人精品区在线播放| 成人一区二区免费视频| 国产美女高潮一区二区三区| 欧美亚洲国产激情| 国产色在线播放| 亚洲美女视频在线观看| 日韩av一区二区在线观看| 亚洲欧美综合自拍| 欧美白人最猛性xxxxx| 伊人久久精品一区二区三区| 丝袜一区二区三区| 久久久久亚洲av无码专区桃色| 国产精品成人aaaaa网站| 加勒比色老久久爱综合网| 日产欧产va高清| 视频一区二区精品的福利| 国产精品成久久久久三级| 久久久精品国产一区二区三区| 欧美日韩一级片在线观看| 国产人妖一区二区| 激情五月综合色婷婷一区二区| 国产精品极品在线| 国产日韩欧美视频| 亚洲国产精品一区制服丝袜| a天堂中文在线官网在线| 国产中文在线| 欧美成人四级hd版| 亚洲午夜国产成人av电影男同| 久久成人免费观看| 日韩最新中文字幕| 久久99久久99精品中文字幕| 日韩女优中文字幕| 先锋影音男人站| 亚洲欧美卡通动漫| 日韩精品在线第一页| 亚洲不卡系列| 人人澡人人爽| 成人性生活av| 亚洲国产午夜伦理片大全在线观看网站| 婷婷综合在线视频| 性爽视频在线| 色中色777| 免费观看在线综合| 欧美性xxxxx| 美女无遮挡网站| 福利h视频在线| 尤物在线网址| 成人黄色在线视频| 国产呻吟对白刺激无套视频在线| 国产一区二区三区黄网站| 欧美午夜不卡在线观看免费| 午夜国产欧美理论在线播放| 91精品综合| 日韩va亚洲va欧美va清高| 日本一区二区视频在线观看| xf在线a精品一区二区视频网站| 麻豆changesxxx国产| 91se在线| 92看片淫黄大片看国产片| 久草在线视频网| 色姑娘综合网|