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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

COM编程之五 动静态链接

發布時間:2024/4/11 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 COM编程之五 动静态链接 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【1】靜態鏈接

靜態鏈接是指由鏈接器在鏈接時將庫的內容加入到可執行程序中的做法。

鏈接器是一個獨立程序,將一個或多個庫或目標文件(先前由編譯器或匯編器生成)鏈接到一塊生成可執行程序。

函數和數據被編譯進一個二進制文件(通常擴展名為.LIB)。

在使用靜態庫的情況下,在編譯鏈接可執行文件時,鏈接器從庫中復制這些函數和數據并把它們和應用程序的其它模塊

組合起來創建最終的可執行文件(.EXE文件)。

具體實例步驟如下

第一步:打開VS2010-->文件-->新建-->工程-->WIN32控制臺項目-->確定(名稱Static)-->靜態庫選項-->預編譯頭文件不選-->Finish

第二步:在這個空項目中,添加一個lib.h文件和一個lib.cpp文件

首先添加 lib.h 聲明文件

1 // Static Project 2 // lib.h 3 // 聲明函數 4 5 #ifndef LIB_H 6 #define LIB_H 7 8 extern "C" int Add(int a, int b); 9 extern "C" int Sub(int a, int b); 10 11 #endif

再添加 lib.cpp 實現文件

1 // Static project 2 // lib.cpp 3 // 實現函數邏輯 4 5 #include "lib.h" 6 7 int Add(int a, int b) 8 { 9 return a + b; 10 } 11 int Sub(int a, int b) 12 { 13 return a - b; 14 }

第三步:保證添加正確后編譯整個工程,確保編譯成功

第四步:在工程Debug文件夾下尋找生成的Static.lib文件,這個文件正是我們需要的靜態鏈接庫

第五步:在目前的工程下,新建空項目TestLib。用以測試靜態鏈接庫的使用效果:

(1)實現方式一

a.?將Static項目下的lib.h和Static.lib這兩個文件復制到TestLib項目的目錄下

b.?在工程目錄中添加已存在的lib.h文件

c.?再新建一個Test.cpp文件。如下:

1 // TestLib project 2 // Test.cpp 3 // 測試靜態鏈接庫 4 5 #include "lib.h" 6 #include <stdlib.h> 7 #include <stdio.h> 8 9 #pragma comment(lib,"Static.lib") 10 11 void main() 12 { 13 printf("%d\n", Add(1, 2)); 14 printf("%d\n", Sub(4, 3)); 15 system("pause"); 16 }

說明:#pragma comment( lib, "Static.lib" ),這一句是顯式的導入靜態鏈接庫。

(2)實現方式二

a.?將Static項目下的lib.h文件復制到TestLib項目的目錄下

b.?在工程目錄中添加已存在的lib.h文件

c.?工程-->屬性-->鏈接器-->輸入-->附加依賴項輸入“Static.lib”

d.?再新建一個Test.cpp文件。如上。

不論使用那種方式。最終編譯 運行的結果都應該是正確鏈接并調用到兩個函數。執行結果不做贅述。

【2】靜態鏈接過程詳解

靜態鏈接即就是把被鏈接項目的.h文件和.cpp文件

首先編譯成為一個靜態鏈接庫文件.lib

然后在鏈接項目的源文件目錄添加

編譯生成的靜態鏈接庫文件.lib 以及 被鏈接項目的.h文件

最后在鏈接項目的源文件中引入.h文件 并顯式導入靜態鏈接庫

即可成功執行鏈接項目調用被鏈接項目的接口功能

其實形象理解如下:

即就是別人把它的產品零件(.h和.cpp文件)

通過車床(靜態鏈接庫工程)

進行加工?(編譯)

生成一個機器產品?(debug文件)

拋棄生成的不必要成分?(debug中除過.lib的其他文件)

提取對客戶有用的核心部分?(debug中的.lib文件)

當然這個核心的部分是獨一無二的(別人擁有版權的權利)

為了人性化的推銷使用他們的產品,他們要把產品說明書(.h文件)附加

送給我們,以便于我們的正確高效使用!

【3】動態鏈接

動態鏈接庫鏈接分為兩種方式:

(1)載入時動態鏈接

即是:編譯之前已經明確知道要調用DLL中的哪幾個函數并且編譯時在目標文件中只保留必要的鏈接信息,而不含DLL函數的代碼。

當程序執行時,利用鏈接信息加載DLL函數代碼并在內存中將其鏈接入調用程序的執行空間中,其主要目的是便于代碼共享。

實例如下:

第一步:打開VS2010-->文件-->新建-->工程-->WIN32控制臺項目-->確定(名稱DLL)-->DLL選項->Finish

第二步:查看新建項目是否存在dllmain.cpp文件,確保為DLL項目。然后在項目中添加以下文件:

a. dll.h

1 // DLL project 2 // DLL.h 3 // 聲明導出函數 4 5 #ifndef DLL_H 6 #define DLL_H 7 8 extern "C" __declspec(dllexport) int add(int x, int y); 9 10 #endif

b. dll.cpp

1 // DLL project 2 // DLL.cpp 3 // DLL 函數實現 4 #include "stdafx.h" 5 #include "dll.h" 6 7 int add(int x, int y) 8 { 9 return x + y; 10 }

編譯整個DLL項目,工程Debug目錄下會生成DLL.lib和DLL.dll文件。裝入時動態鏈接必需二者。

第三步:在目前的工程下,新建空項目TestDLL。用以測試裝入時動態鏈接庫的效果:

將DLL項目Debug目錄下的DLL.dll和DLL.lib這兩個文件復制到TestDLL項目的目錄下

再新建一個TestDll.cpp文件。如下:

1 //ps:該文件屬于TestDll項目,與DLL項目同屬于一個工程 2 // TestDll project 3 // TestDll.cpp 4 // 靜態調用DLL實現 5 6 #include<stdio.h> 7 8 #pragma comment(lib,"dll.lib") 9 extern "C" __declspec(dllimport) int add(int x, int y); 10 11 void main( ) 12 { 13 int result = add(20, 30); 14 printf("%d", result); 15 }

第四步:編譯TestDLL項目。執行結果應該正確調用add函數功能。

過程進行完畢,但是過程中存在很多疑問。且聽分析:

1. .lib文件詳解

.lib 文件為Windows系統中的庫文件,相當于Linux中的.a 或 .o、.so文件

lib有 靜態lib 和 動態lib之分

a:?靜態lib將導出聲明和實現都放在lib中。編譯后所有代碼都嵌入到宿主程序。(如上靜態鏈接模塊中編譯后得到的lib文件)

b:?動態lib相當于一個.h文件,是對實現部分(.dll文件)的導出部分的聲明。

編譯后只是將導出聲明部分編譯到宿主程序中,運行時候需要相應的dll文件支持。

一個lib文件是obj文件的集合。

當然,其中還夾雜著其他一些輔助信息,目的是為了讓編譯器能夠準確找到對應的obj文件。

2. 如下兩句的作用:

1 extern "C" __declspec(dllexport) int add(int x, int y); 2 extern "C" __declspec(dllimport) int add(int x, int y);

在動態鏈接庫中__declspec(dllexport)作用是導出聲明,__declspec(dllimport)作用是導入聲明。

關于導出導入聲明還有另外一種方式即采用模塊定義文件(.def),下面將示例。

3.?#pragma comment(lib,"dllTest.lib")作用是告訴編譯器與DLL相對應的.lib文件所在的路徑及文件名。

程序員在建立一個DLL文件時,連接器會自動為其生成一個對應的.lib文件。

該文件包含了DLL導出函數的符號名及序號(并不含有實際的代碼)。

在應用程序里,.lib文件將作為DLL的替代文件參與編譯。

總而言之,靜態鏈接方式編譯生成應用程序時,應用程序中調用的與.lib文件中導出符號相匹配的函數符號將進入到生成的EXE文件中,.lib文件中所包含的與之對應

的DLL文件的文件名也被編譯器存儲在EXE文件內部。

當應用程序運行過程中需要加載DLL文件時,Windows將根據這些信息發現并加載DLL,然后通過符號名實現對DLL函數的動態鏈接。

這樣,EXE將能直接通過函數名調用DLL的輸出函數,就像調用程序內部的其它函數一樣。

(2)運行時動態鏈接

即是:編譯之前并不知道將會調用哪些DLL函數,完全是在運行過程中根據需要決定應調用哪個函數,并用LoadLibrary和GetProcAddress動態獲得DLL函數的入口地址。

實例如下:

第一步:打開VS2010-->文件-->新建-->工程-->WIN32控制臺項目-->確定(名稱DLL)-->DLL選項->Finish

第二步:查看新建項目是否存在dllmain.cpp文件,確保為DLL項目。然后在項目中添加以下文件:

a. dll.cpp

1 // DLL.cpp 2 // 實現文件 3 4 #include "stdafx.h" 5 6 int add(int a, int b) 7 { 8 return a + b; 9 }

b. dll.def

1 ; Dll.def : 導出DLL函數 2 LIBRARY DLL 3 EXPORTS 4 add @ 1

編譯整個DLL項目,工程Debug目錄下會生成DLL.lib和DLL.dll文件。裝入時動態鏈接必需二者。

如果VS2010環境下只有.dll文件沒有生成.lib文件

需要在項目-->屬性-->連接器-->輸入-->模塊定義文件中添加指定模塊定義文件

第三步:在目前的工程下,新建空項目TestDLL。用以測試裝入時動態鏈接庫的效果:

新建一個TestDll.cpp文件。如下:

1 // TestDLL project 2 // TestDLL.cpp 測試動態鏈接 3 4 #include <stdio.h> 5 #include <Windows.h> 6 using namespace std; 7 8 typedef int(*lpAddFun)(int, int); //宏定義函數指針類型 9 10 int main(int argc, char *argv[]) 11 { 12 HINSTANCE hDll; //DLL句柄 13 lpAddFun addFun; //函數指針 14 wchar_t wchar[] = L"..\\Debug\\DLL.dll"; 15 hDll = LoadLibrary(wchar); 16 if (hDll != NULL) 17 { 18 addFun = (lpAddFun)GetProcAddress(hDll, "add"); 19 if (addFun != NULL) 20 { 21 int result = addFun(20, 30); 22 printf("%d\n", result); 23 } 24 FreeLibrary(hDll); 25 } 26 return 0; 27 }

第四步:編譯TestDLL項目。執行結果應該正確調用add函數功能。

1. def文件

a:?模塊定義 (.def) 文件為銜接器提供有關被鏈接程序的導出、屬性及其他方面的信息。生成 DLL 時,.def 文件最有用。

b: .def文件的規則為:

(1) LIBRARY語句說明.def文件相應的DLL;

(2) EXPORTS語句后列出要導出函數的名稱。可以在.def文件中的導出函數名后加@n,表示要導出函數的序號為n(在進行函數調用時,這個序號將發揮其作用);

(3) .def 文件中的注釋由每個注釋行開始處的分號 (;) 指定,且注釋不能與語句共享一行。

2. LoadLibrary 加載動態庫; GetProcAddress 獲取DLL函數的地址; FreeLibrary 釋放動態庫。

【4】動態鏈接分析

相比靜態鏈接,動態鏈接有幾個優點:

1.多個進程在同一基地址裝載相同DLL,只需要一個共享DLL即可,它在物理地址空間內共享。

2.DLL內的函數變化,只要其輸入輸入參數、調用格式沒有變,應用程序自身不必重新編譯。靜態鏈接需要重新編譯。

3.DLL提供異步支持。比如應用程序裝載DLL時,用DLL支持一個無效設備。

4.不同語言編寫的應用程序可以用約定的調用格式調用DLL函數。

潛在缺點是應用程序不是相對獨立的。

啟動裝載動態鏈接時,DLL不存在,程序不被裝載。

運行裝載時,如果DLL不存在,由程序處理。

【5】靜態鏈接 與 動態鏈接 總結

靜態鏈接是在生成可執行程序的時候就把庫中的內容加入到程序中。

載入時動態鏈接是在將功能模塊讀入內存時把動態庫中調用到的相關模塊的內容載入內存。

運行時動態鏈接是在執行程序調用到模塊內容時再將動態庫中的相應模塊載入到內存。

這里有兩個時間問題。一是載入時間,二是執行時間。

靜態鏈接由于是在一開始就把所有模塊都加載進入內存,所以如果模塊很多的話效率就會被大大拉低。

載入時動態鏈接是分別載入,當把一個模塊載入內存時檢查有調用關系的模塊載入,比靜態鏈接節省了許多開銷。

運行時動態鏈接則是把當前模塊調用的模塊推遲到調用的時候再載入。

三者之間的關系就像是機槍,沖鋒槍和shou槍

機槍在一開始就把所有子彈裝好,開槍的時候很快,但也很笨重。

沖鋒槍則是將子彈分彈夾存好,輕便了許多,但是會有一段裝填時間。

shou槍就更加輕便了,但是彈夾容量更小,裝填的頻率又變高了。

【6】組件與動態鏈接庫

動態鏈接庫簡稱為DLL。一個組件實際上并不是一個DLL。

DLL只是一個組件服務器。或者說是一種發行組件的方式。

組件實質上應看成是在DLL中所實現的接口集。

DLL只是一種形式,而組件才是實質。

而組件需要放入DLL中,在客戶獲取某個組件接口指針時:

它必須先將相應的DLL裝載到其進程空間并創建此組件。

CreateInstance可以建立一個組件實例并給客戶返回一個IUnknown接口指針。

CreateInstance是DLL中唯一需要客戶顯式鏈接的函數。

而客戶對于組件所需的所有函數通過一個接口指針而訪問到。

?

?

Good ?Good ?Study, Day ?Day ?Up.

順序 ?選擇 ?循環 ?總結

總結

以上是生活随笔為你收集整理的COM编程之五 动静态链接的全部內容,希望文章能夠幫你解決所遇到的問題。

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