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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

VC++动态库封装及调用

發布時間:2025/3/15 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC++动态库封装及调用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://blog.csdn.net/zhangfuliang123/article/details/71515796

?

一直對動態庫的封裝理解不是很透徹,雖然之前寫過一個Demo,不過并沒有真正的理解。所以寫下來,幫助自己理解下。

1、一個程序從源文件編譯生成可執行文件的步驟:

預編譯 --> ?編譯 --> ?匯編 --> 鏈接

(1)預編譯,即預處理,主要處理在源代碼文件中以“#”開始的預編譯指令,如宏展開、處理條件編譯指令、處理#include指令等。

(2)編譯過程就是把預處理完的文件進行一系列詞法分析、語法分析、語義分析以及優化后生成相應的匯編代碼文件。

(3)匯編是將匯編代碼轉變成二進制文件。

(4)鏈接將二進制文件鏈接成一個可執行的命令,主要是把分散的數據和代碼收集并合成一個單一的可加載并可執行的的文件。鏈接可以發生在代碼靜態編譯、程序被加載時以及程序執行時。鏈接過程的主要工作是符號解析和重定位。

2、庫?

庫是一組目標文件的包,就是一些最常用的代碼編譯成目標文件后打包存放。而最常見的庫就是運行時庫(Runtime Library),如C運行庫CRT.

庫一般分為兩種:靜態庫(.a 、.lib)動態庫(.so 、.dll )所謂靜態、動態是指鏈接過程。?

3、靜態庫與動態庫

區別:

(1)lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,記錄了dll中函數的入口和位置,dll中是函數的具體內容;如果只有lib文件,那么這個lib文件是靜態編譯出來的,索引和實現都在其中。使用靜態編譯的lib文件,在運行程序時不需要再掛動態庫,缺點是導致應用程序比較大,而且失去了動態庫的靈活性,發布新版本時要發布新的應用程序才行。
(3)動態鏈接的情況下,有兩個文件:一個是LIB文件,一個是DLL文件。LIB包含被DLL導出的函數名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件鏈接到DLL文件。在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中相應函數代碼的地址,從而節省了內存資源。DLL和LIB文件必須隨應用程序一起發行,否則應用程序會產生錯誤。如果不想用lib文件或者沒有lib文件,可以用WIN32 API函數LoadLibrary、GetProcAddress裝載。

------這里主要講動態庫的優點特性。--------

靜態庫:函數和數據被編譯進一個二進制文件(通常擴展名為.LIB)。在使用靜態庫的情況下,在編譯鏈接可執行文件時,鏈接器從庫中復制這些函數和數據并把它們和應用程序的其它模塊組合起來創建最終的可執行文件(.EXE文件)。
在使用動態庫的時候,往往提供兩個文件:一個引入庫和一個DLL。引入庫包含被DLL導出的函數和變量的符號名,DLL包含實際的函數和數據。在編譯鏈接可執行文件時,只需要鏈接引入庫,DLL中的函數代碼和數據并不復制到可執行文件中,在運行的時候,再去加載DLL,訪問DLL中導出的函數。

靜態庫有兩個重大缺點:

1)空間浪費

2)靜態鏈接對程序的更新、部署和發布會帶來很多麻煩。一旦程序中有任何模塊更新,整個程序就要重新鏈接,發布給用戶。

動態鏈接的基本思想:把程序按照模塊拆分成各個相對獨立的部分,在程序運行時才將它們鏈接在一起形成一個完整的程序,而不是想靜態鏈接一樣把所有的程序模塊都鏈接成一個單獨的可執行文件。

特點:

1)代碼共享,所有引用該動態庫的可執行目標文件共享一份相同的代碼與數據。

2)程序升級方便,應用程序不需要重新鏈接新版本的動態庫來升級,理論上只要簡單地將舊的目標文件覆蓋掉。

3)在運行時可以動態地選擇加載各種應用程序模塊

下面重點介紹Windows下動態鏈接庫DLL.

DLL即動態鏈接庫(Dynamic-Link Libaray)的縮寫,相當于Linux下的共享對象。Windows系統中大量采用了DLL機制,甚至內核的結構很大程度依賴與DLL機制。Windows下的DLL文件和EXE文件實際上是一個概念,都是PE格式的二進制文件。一般的動態庫程序有lib文件和dll文件,lib文件是編譯時期連接到應用程序中的,而dll文件是運行時才會被調用的。

為了更好的理解DLL,首先介紹一下導出和導入的概念。

(1)導出與導入

在ELF(Linux下動態庫的格式),共享庫中所有的全局函數和變量在默認情況下都可以被其他模塊使用,即ELF默認導出所有的全局符號。DLL不同,需要顯式地“告訴”編譯器需要導出某個符號,否則編譯器默認所有的符號都不導出。

程序使用DLL的過程其實是引用DLL中導出函數和符號的過程,即導入過程。對于從其他DLL導入的符號,需要使用“__declspec(dllimport)”顯式聲明某個符號為導入符號。在ELF中,使用外部符號時,不需要額外聲明該符號是從其他共享對象導入的。

指定符號的導入導出一般有如下兩種方法:

1)MSVC編譯器提供了一系列C/C++的擴展來指定符號的導入導出,即__declspec屬性關鍵字。

__declspec(dllexport) 表示該符號是從本DLL導出的符號

__declspec(dllimport) 表示該符號是從別的DLL中導入的

2)使用“.def”文件來聲明導入到導出符號,詳細參考《程序員的自我修養--鏈接、裝載與庫》。

應用程序使用DLL可以采用兩種方式:一種是隱式鏈接(調用),另一種是顯式鏈接。在使用DLL之前首先要知道DLL中函數的結構信息。
4、DLL創建?

下面是頭文件內容:創建工程時有默認的導出函數,這里將其刪除掉重新寫的。

// 下列 ifdef 塊是創建使從 DLL 導出更簡單的 // 宏的標準方法。此 DLL 中的所有文件都是用命令行上定義的 MYDLL_EXPORTS // 符號編譯的。在使用此 DLL 的 // 任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將 // MYDLL_API 函數視為是從 DLL 導入的,而此 DLL 則將用此宏定義的 // 符號視為是被導出的。 #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endifextern "C" MYDLL_API double seekArea(int r, int h);


這里將seek函數聲明為導出函數;

當定義了符號MYDLL_EXPORTS,MYDLL_API被設置為 __declspec(dllexport)修飾符,This modifier enables the function to be exported by the DLL so that it can be used by other applications。若未定義則TMYDLL_API被設置為__declspec(dllimport),This modifier enables the compiler to optimize the importing of the function from the DLL for use in other applications。當DLL項目生成時,MYDLL_EXPORTS默認是定義的,所以默認設置的是__declspec(dllexport) 修飾符。?

// myDLL.cpp : 定義 DLL 應用程序的導出函數。 //封裝圓柱體的體積#include "stdafx.h" #include "stdio.h" #include "myDLL.h"void show(){printf("Call the library function.\n");printf("***************************\n"); } double area(int r){return 3.14*r*r; }MYDLL_API double seekArea(int r, int h){show();double under = 3.14*r*r;double v = under*h;return v; }

然后編譯就會生成對應的dll文件,同時也會生成對應的lib文件。?
注意:a.DLL中導出函數的聲明有兩種方式:在函數聲明中加上__declspec(dllexport);采用模塊定義(.def)文件聲明。詳見:http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792099.html?
  b.對于C文件創建dll時或者想使用C編譯器創建dll時,建議使用 extern “C” 標志,參見extern "C"的簡單解析。

5.DLL的隱式調用

隱式鏈接采用靜態加載的方式,比較簡單,需要.h、.lib、.dll三件套。新建“控制臺應用程序”或“空項目”。配置如下:?
項目->屬性->配置屬性->VC++ 目錄-> 在“包含目錄”里添加頭文件testdll.h所在的目錄?
項目->屬性->配置屬性->VC++ 目錄-> 在“庫目錄”里添加頭文件testdll.lib所在的目錄?
項目->屬性->配置屬性->鏈接器->輸入-> 在“附加依賴項”里添加“testdll.lib”(若有多個 lib 則以空格隔開) 。?//你也可以在項目屬性中設置庫的鏈接,#pragma comment(lib, "DLLSample.lib")

庫文件頭文件等目錄設置,本文將庫文件及頭文件拷貝到工程目錄下DLL文件夾下

添加LIB依賴項

#調用的源程序#

// callmyDLL.cpp : 定義控制臺應用程序的入口點。 //包含頭頭文件,函數聲明#include "stdafx.h" #include "stdlib.h" #include "myDLL.h" extern "C" _declspec(dllimport) double seekArea(int r, int h);int _tmain(int argc, _TCHAR* argv[]) {int r = 1, h = 5;double area = seekArea(r, h);printf("Area is:%f\n", area);system("pause");return 0; }

運行時最后一步:將動態庫文件拷貝到可執行文件目錄下,否則會出現如下錯誤。

6、DLL顯示調用

對于顯示連接,即動態加載我們需要調用LoadLibrary
在MSDN中:HMODULE WINAPI LoadLibrary(
??__in ?LPCTSTR lpFileName
);
它的功能是映射一個可執行模塊到調用進程的地址空間。由此我們知道顯示調用就是函數指針來調用函數。

Steps:
1、聲明頭文件<windows.h>,說明我想用windows32方法來加載和卸載DLL
2、然后用typedef定義一個指針函數類型.typedef ?void(*fun) //這個指針類型,要和你調用的函數類型和參數保持一致
3、定一個句柄實例,用來取DLL的實例地址。HINSTANCE hdll;
格式為hdll=LoadLibrary(“DLL地址”);這里字符串類型是LPSTR,當是unicode字符集的時候會不行,
因此要在配置-屬性-常規里面把默認字符集“unicode”改成支持多字符擴展即可。
4、取的地址要判斷,返回的句柄是否為空,如果為無效句柄,那么要釋放加載DLL所占用的內存。
5、定義一個函數指針,用來獲取你要用的函數地址。
??然后通過GetProcAdress來獲取函數的地址,參數是DLL的句柄和你要調用的函數名:比如:FUN=(fun)GetProcAdress(hdll,"sum");
??這里也要判斷要函數指針是否為空,如果沒取到要求的函數,那么要釋放句柄。
6、然后通過函數指針來調用函數。
7、調用結束后,就釋放句柄FreeLibrary(hdll);

// callDLLSee.cpp : 定義控制臺應用程序的入口點。 //通過調用windowsAPI 來加載和卸載DLL #include "stdafx.h" #include "Windows.h" typedef double(*Dllfun)(int , int);int _tmain(int argc, _TCHAR* argv[]) {Dllfun funName;HINSTANCE hdll;//put DLL under the Debug path //use _T 設置為寬字符hdll = LoadLibrary( _T("myDLL.dll"));if (hdll == NULL){FreeLibrary(hdll);}funName = (Dllfun)GetProcAddress(hdll, "seekArea");if (funName == NULL){FreeLibrary(hdll);}int r = 1, h = 10;double area = funName(r, h);printf("area = %f\n", area);FreeLibrary(hdll);return 0; }

?

?

?

?

總結

以上是生活随笔為你收集整理的VC++动态库封装及调用的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产毛片一区二区三区va在线 | 亚洲三级精品 | 日本三级中文字幕在线观看 | 插插影视 | 强行无套内谢大学生初次 | 古代玷污糟蹋np高辣h文 | 日本韩国视频 | 久久精品国产亚洲AV成人雅虎 | 玖玖玖精品 | 国产区免费 | 三点尽露的大尺度国产 | 热久久中文 | 天天操天天干天天干 | 精品日韩视频 | 91综合色| 免费看黄色漫画 | 日本精品在线看 | 欧美激情免费在线观看 | 乳色吐息在线看 | 福利综合网 | 亚洲性生活片 | 欧美日韩精品一二三区 | 欧美肥老妇视频 | 人人干人人爱 | 哪里可以免费看av | 日韩福利视频导航 | 精品人妻少妇嫩草av无码 | 亚洲无人区码一码二码三码的含义 | 麻豆视频免费观看 | 久久精品国产一区二区电影 | 黄色一级大片在线免费看国产 | 最新中文字幕久久 | 色哟哟视频 | 国产乱子伦精品 | 能免费看18视频网站 | 中文字幕高清在线免费播放 | 日本黄色免费 | wwwjizzzcom| 成人高潮片免费视频 | 青青草日韩 | 丁香婷婷综合网 | 涩涩成人网 | 午夜在线观看免费视频 | 亚洲爱爱图 | 成人av18| 爱爱的网站| 玖玖爱国产| 亚洲天堂一区二区在线 | 浪潮av一区二区三区 | 精品人妻互换一区二区三区 | 精品久久久久久亚洲 | 国产激情自拍视频 | 国产女厕一区二区三区在线视 | 人妻无码中文字幕免费视频蜜桃 | 亚洲精品一卡 | 中文字幕少妇在线三级hd | www.youjizz.com日本 | 亚洲老女人 | 红桃视频在线播放 | 日韩精品免费在线观看 | 免费黄色小视频 | 亚洲网站在线 | 美女隐私无遮挡 | 国产a免费| 亚洲av综合一区二区 | 免费观看国产视频 | 97超碰人人澡 | 国产69精品久久久久久久 | 国产乱子伦一区二区 | 妞干网精品 | 日韩不卡一二三 | 在线免费看av | 国产精品一区二区网站 | 国产学生美女无遮拦高潮视频 | 日韩精品中文字 | 久久国产一区 | 精品国产无码在线观看 | 噜噜噜噜私人影院 | 青青草一区 | 伦理片一区二区 | 最近中文字幕一区二区 | 日韩欧美一二三区 | 91视频污在线观看 | 免费看欧美一级特黄a大片 国产免费的av | 插吧插吧网 | 日韩精品在线一区 | 无码人妻精品一区二区蜜桃网站 | 在线观看精品国产 | 日本少妇久久久 | 久草小说 | 免费观看黄色 | 国产伊人精品 | 成人免费a级片 | 日韩xxx高潮hd | 菲律宾av | 96视频在线观看 | 国产在线观看免费视频今夜 | 国产ts在线观看 | 无码成人一区二区 |