1. 程式人生 > >MFC下DLL/lib的呼叫

MFC下DLL/lib的呼叫

 1、簡介:
dll和.lib都是程式集合,便於程式碼重用。都是二進位制的檔案。

.dll也叫動態連結庫,與程式連結的方式為執行時連結(run-time linked),為PE(portable executable)格式,也就是程完整的程式。.exe、.dll、.fon、.mod、.drv、.ocx等等都是動態連結庫。如.exe為系統呼叫的函式集合。.dll不存在同名引用,且有匯出表,與匯入表。

.lib也叫靜態連結庫,在編譯時與程式連結(link-time linked),將“嵌入”到程式中。會有冗餘(程式檔案程式碼的冗餘和執行時記憶體儲存的冗餘),當兩個lib相連結時地址會重新建立同。在使用.lib之前,要在程式原始碼中引用lib對應的標頭檔案.h,這些標頭檔案告訴編譯器.lib中有什麼。

在生成.dll時,通常會生成一個.lib。這個.lib將被編譯到程式檔案中,在程式執行的時候,告訴作業系統將要載入的.dll。這個.lib包括對應.dll的檔名、順序表(ordinal table包含.dll暴露出的函式的進入點),在程式執行的時候,通過順序表實現函式的跳轉。

如果不想使用或者找不到該.lib,可以用LoadLibrary () Win32 API和GetLibrary () Win32 API。

VC IDE為了實現程式除錯,會生成.PDB(程式資料庫,二進位制),裡面包含原始檔呼叫的檔案資訊和行資訊。這樣就可以逐行除錯了。

開啟.lib,檢視其ascii碼,可以看到如@@My_Function1123的函式名,這些名稱在編譯時被編譯器運用mangling mechanism進行了名稱的mangling。

在程式的編譯過程中,如果出現如下錯誤“unresolved symbol 
[email protected]
”,通常是因為找不到引用過的外部函式對應的.lib檔案,或者是.c、.cpp原始檔。


2、使用:
用DLL,首先需要將DLL檔案映像到使用者程序的地址空間中,然後才能進行函式呼叫,這個函式和程序內部一般函式的呼叫方法相同。Windows提供了兩種將DLL映像到程序地址空間的方法:

  1、隱式的載入時連結

  這種方法需要DLL工程經編譯產生的LIB檔案,此檔案中包含了DLL允許應用程式呼叫的所有函式的列表,當連結器發現應用程式呼叫了LIB檔案列出的某個函式,就會在應用程式的可執行檔案的檔案映像中加入一些資訊,這些資訊指出了包含這個函式的DLL檔案的名字。當這個應用程式執行時,也就是它的可執行檔案被作業系統產生映像檔案時,系統會檢視這個映像檔案中關於DLL的資訊,然後將這個DLL檔案映像到程序的地址空間。

  系統通過DLL檔案的名稱,試圖載入這個檔案到程序地址空間時,它尋找DLL 檔案的路徑按照先後順序如下:

  ·程式執行時的目錄,即可執行檔案所在的目錄;

  ·當前程式工作目錄

  ·系統目錄:對於Windows95/98來說,可以呼叫GetSystemDirectory函式來得到,對於WindowsNT/2000來說,指的是32位Windows的系統目錄,也可以呼叫GetSystemDirectory函式來得到,得到的值為SYSTEM32。

  ·Windows目錄

  ·列在PATH環境變數中的所有目錄

  VC中載入DLL的LIB檔案的方法有以下三種:

  ①LIB檔案直接加入到工程檔案列表中

  在VC中開啟File View一頁,選中工程名,單擊滑鼠右鍵,然後選中"Add Files to Project"選單,在彈出的檔案對話方塊中選中要加入DLL的LIB檔案即可。

  ②設定工程的 Project Settings來載入DLL的LIB檔案

  開啟工程的 Project Settings選單,選中Link,然後在Object/library modules下的文字框中輸入DLL的LIB檔案。

  ③通過程式程式碼的方式

   加入預編譯指令#pragma comment (lib,"*.lib"),這種方法優點是可以利用條件預編譯指令連結不同版本的LIB檔案。因為,在Debug方式下,產生的LIB檔案是Debug 版本,如Regd.lib;在Release方式下,產生的LIB檔案是Release版本,如Regr.lib。

  當應用程式對DLL的LIB檔案載入後,還需要把DLL對應的標頭檔案(*.h)包含到其中,在這個標頭檔案中給出了DLL中定義的函式原型,然後宣告。

  2、顯式的執行時連結

  隱式連結雖然實現較簡單,但除了必須的*.dll檔案外還需要DLL的*.h檔案和*.lib檔案,在那些只提供*.dll檔案的場合就無法使用,而只能採用顯式連結的方式。這種方式通過呼叫API函式來完成對DLL的載入與解除安裝,其能更加有效地使用記憶體,在編寫大型應用程式時往往採用此方式。這種方法程式設計具體實現步驟如下:

  ①使用Windows API函式Load Library或者MFC提供的AfxLoadLibrary將DLL模組映像到程序的記憶體空間,對DLL模組進行動態載入。

  ②使用GetProcAddress函式得到要呼叫DLL中的函式的指標。

  ③不用DLL時,用Free Library函式或者AfxFreeLibrary函式從程序的地址空間顯式解除安裝DLL。

呼叫DLL有兩種方法:靜態呼叫和動態呼叫.
(一).靜態呼叫其步驟如下:
1.把你的youApp.DLL拷到你目標工程(需呼叫youApp.DLL的工程)的Debug目錄下;
2.把你的youApp.lib拷到你目標工程(需呼叫youApp.DLL的工程)目錄下;
3.把你的youApp.h(包含輸出函式的定義)拷到你目標工程(需呼叫youApp.DLL的工程)目錄下;
4.開啟你的目標工程選中工程,選擇Visual C++的Project主選單的Settings選單;
5.執行第4步後,VC將會彈出一個對話方塊,在對話方塊的多頁顯示控制元件中選擇Link頁。然後在Object/library modules輸入框中輸入:youApp.lib
6.選擇你的目標工程Head Files加入:youApp.h檔案;
7.最後在你目標工程(*.cpp,需要呼叫DLL中的函式)中包含你的:#include "youApp.h"
注:youApp是你DLL的工程名。

(二).動態呼叫其程式如下:
動態呼叫時只需做靜態呼叫步驟1.
01{
02     HINSTANCE hDllInst = LoadLibrary("youApp.DLL");
03     if(hDllInst)
04     {
05         typedef DWORD (WINAPI*MYFUNC)(DWORD,DWORD);
06        MYFUNCyouFuntionNameAlias=NULL;
07        // youFuntionNameAlias 函式別名
08
        youFuntionNameAlias= (MYFUNC)GetProcAddress(hDllInst,"youFuntionName");
09        // youFuntionName 在DLL中宣告的函式名
10         if(youFuntionNameAlias)
11        {
12            youFuntionNameAlias(param1,param2);
13        }
14        FreeLibrary(hDllInst);
15     }
16 }

顯式(靜態)呼叫:
LIB + DLL + .H,注意.H中dllexport改為dllimport
隱式(動態)呼叫:
DLL + 函式原型宣告,先LoadLibrary,再GetProcAddress(即找到DLL中函式的地址),不用後FreeLibrary

--------------------------------------
動態連結庫DLL的連結
http://blog.donews.com/mmycly/archive/2006/06/15/917076.aspx

應用程式使用DLL可以採用兩種方式:一種是隱式連結,另一種是顯式連結。在使用DLL之前首先要知道DLL中函式的結構資訊。Visual C++6.0在VC\bin目錄下提供了一個名為Dumpbin.exe的小程式,用它可以檢視DLL檔案中的函式結構。另外,Windows系統將遵循下面的搜尋順序來定位DLL: 1.包含EXE檔案的目錄,2.程序的當前工作目錄, 3.Windows系統目錄, 4.Windows目錄,5.列在Path環境變數中的一系列目錄。

(一).隱式連結
隱式連結就是在程式開始執行時就將DLL檔案載入到應用程式當中。實現隱式連結很容易,只要將匯入函式關鍵字_declspec(dllimport)函式名等寫到應用程式相應的標頭檔案中就可以了。下面的例子通過隱式連結呼叫MyDll.dll庫中的Min函式。首先生成一個專案為TestDll,在 DllTest.h、DllTest.cpp檔案中分別輸入如下程式碼:

01 //Dlltest.h
02
     #pragma comment(lib,"MyDll.lib")
03     extern "C"_declspec(dllimport)intMax(inta,int b);
04     extern "C"_declspec(dllimport)intMin(inta,int b);
05 //TestDll.cpp
06
 #include
07 #include"Dlltest.h"
08 voidmain()
09 {
10     int a;
11     a=min(8,10)
12     printf("比較的結果為%d\n"a);
13 }



在建立DllTest.exe檔案之前,要先將MyDll.dll和MyDll.lib拷貝到當前工程所在的目錄下面,也可以拷貝到windows的 System目錄下。如果DLL使用的是def檔案,要刪除TestDll.h檔案中關鍵字extern "C"。TestDll.h檔案中的關鍵字Progam commit是要Visual C+的編譯器在link時,連結到MyDll.lib檔案,當然,開發人員也可以不使用#pragma comment(lib,"MyDll.lib")語句,而直接在工程的Setting->Link頁的Object/Moduls欄填入 MyDll.lib既可。

程式設計時用ad.h,ad.lib,放在專案當前目錄裡
在標頭檔案中加入#include "ad.h"
在Project Setting–>Link–>Object/library modules加入ad.lib
執行時將ad.dll跟你的程式放在同一目錄

(二).顯式連結
顯式連結是應用程式在執行過程中隨時可以載入DLL檔案,也可以隨時解除安裝DLL檔案,這是隱式連結所無法作到的,所以顯式連結具有更好的靈活性,對於解釋性語言更為合適。不過實現顯式連結要麻煩一些。在應用程式中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動態連結庫調進來,動態連結庫的檔名即是上述兩個函式的引數,此後再用GetProcAddress()獲取想要引入的函式。自此,你就可以象使用如同在應用程式自定義的函式一樣來呼叫此引入函數了。在應用程式退出之前,應該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動態連結庫。下面是通過顯式連結呼叫DLL中的Max函式的例子。

01 #include
02 #include
03 voidmain(void)
04 {
05     typedef int(*pMax)(inta,int b);
06     typedef int(*pMin)(inta,int b);
07     HINSTANCE hDLL;
08     PMax Max
09     HDLL=LoadLibrary("MyDll.dll");//載入動態連結庫MyDll.dll檔案;
10     Max=(pMax)GetProcAddress(hDLL,"Max");
11     A=Max(5,8);
12     Printf("比較的結果為%d\n"a);
13     FreeLibrary(hDLL);//解除安裝MyDll.dll檔案;
14
 }


在上例中使用型別定義關鍵字typedef,定義指向和DLL中相同的函式原型指標,然後通過LoadLibray()將DLL載入到當前的應用程式中並返回當前DLL檔案的控制代碼,然後通過GetProcAddress()函式獲取匯入到應用程式中的函式指標,函式呼叫完畢後,使用 FreeLibrary()解除安裝DLL檔案。在編譯程式之前,首先要將DLL檔案拷貝到工程所在的目錄或Windows系統目錄下。

使用顯式連結應用程式編譯時不需要使用相應的Lib檔案。另外,使用GetProcAddress()函式時,可以利用 MAKEINTRESOURCE()函式直接使用DLL中函數出現的順序號,如將GetProcAddress(hDLL,"Min")改為 GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函式Min()在DLL中的順序號是2),這樣呼叫DLL中的函式速度很快,但是要記住函式的使用序號,否則會發生錯誤。

MFC dll 生成和使用

課題來源: 為了實現將串列埠傳上來的資料作圖,在網上下載了一個CLPLOT的封裝類。

問題:該分裝類就像是一個控制元件,可以靈活呼叫。但是,存在一個問題,就是不知道如何快捷的生成exp,lib,dll檔案。

解決方法:

?         開啟工程,第一步,我們需要生成lib,exp檔案。開啟project->settings,出現如圖(1)對話方塊。在link選項裡,將output file name 修改為:xxx.lib,Object/library modules 空出。OK之後,直接build,執行,然後就會生成exp,lib檔案,結果如下:

“Creating library Debug/clPlot.lib and object Debug/clPlot.exp“

於是便在debug裡面成功生成了exp,lib檔案。 

?         接著我們需要生成dll文見。將exp,lib檔案從debug資料夾中拷貝出來(也可以不考,修改link中相應的路徑即可),放到工程目錄下面。

?         開啟project->settings,出現如圖(2)對話方塊。在link選項裡,將output file name 修改為:Debug/xxx.dll(注意:一開始我只寫了XXX.dll,找不到dll檔案,最好具體點),Object/library modules 中直接寫lib的路徑。在這裡,由於已經考到工程目錄下,所以直接寫xxx.lib即可。 

?         Build,執行,即可生成DLL檔案。

?         然後就可以通過使用exp,ib,dll, .h檔案,就可以使用自己建立的類,控制元件。 

(其實直接在工程中建立的時候,選擇MFC AppWizard[dll]既可以通過bulid生成dll,lib,exp檔案。

“Creating library Debug/dllTest.lib and object Debug/dllTest.exp“)

相關推薦

MFCDLL/lib呼叫

 1、簡介: dll和.lib都是程式集合,便於程式碼重用。都是二進位制的檔案。 .dll也叫動態連結庫,與程式連結的方式為執行時連結(run-time linked),為PE(portable executable)格式,也就是程完整的程式。.exe、.dll、.fon、.mod、.drv、.ocx等等都

MFCDLL程式設計(圖解)一定要認真看(包含了很多東西)

DLL(Dynamic Link Library,動態連結庫)是微軟公司為Windows和OS/2作業系統設計一種供應用程式在執行時呼叫的共享函式庫。DLL是應用程式的一種擴充套件,也是軟體共享和重用的傳統方法。 DLL除了可同時被多個應用程式共享外,還可以在不改變呼叫

MFC/Qt呼叫caffe原始碼(二)---MFC呼叫caffe的動態連線庫dll檔案

首先,先看下最後的效果吧。 win7 vs2013 新建一個MFC 工程 注:MFC中如何最簡便的方法將圖片顯示到對話方塊中?大家可以搜下,很多種方法,但是我採用的是最簡單的方法,即將opencv視窗繫結到MFC的PIcture control上。 在:

關於MFCDLL的製作和呼叫

在做MFC程式的時候用到了DLL,所以查詢總結了一下。 一. 製作DLL流程 為什麼都沒有段落符號與標號。。。先建立DLL工程、類,編寫DLL函式;編譯連結產生DLL檔案(普通工程產生的EXE檔案,DLL產生的是DLL檔案)。此時DLL檔案還不能呼叫。應用程式要想訪問某個D

Windowslib檔案和dll檔案

一個軟體執行,通常需要一些必備的靜態庫和動態庫。靜態庫和動態庫本身,其實可以作為軟體執行所必需的環境來理解。靜態庫是指靜態的,一般在程式連結時早已放到程式中。動態庫是連結時告訴程式此環境存在,在執行時才呼叫和載入。在Windows下,靜態庫的檔名為lib,動態庫為dll。

VC++6.0 動態庫的建立與呼叫(非MFCdll

非MFC動態庫的建立。。。。 lib.cpp#ifndef LIB_H #define LIB_H //宣告add為dll的匯出函式. extern "C" int _declspec(dllexport)add(int x,int y); #endif /*lib.

VS開發環境生成和呼叫dll出現的問題和解決方法-1

dll生成和呼叫方法網上很多,省略。  1 build之後只生成了dll檔案,沒有lib檔案。 原因和方法:沒有對任何的類或者函式定義DLL interface,需要對類或者函式定義DLL interface,定義方法如下: 對於類: class _declspec(

linux的.a和.so,對比windowslibdll

兩種庫 Linux下的靜態庫以.a結尾(Winodws下為.lib)Linux下的動態庫以.so 或 .so.y結尾,其中y代表版本號(Windows下為.dll),而且,Linux下的庫必須以lib開頭,用於系統識別(如:libjpeg.a libsdl.so)靜態庫必

注意mfconinitdialog()和onsize()的呼叫順序

BOOL dddd::OnInitDialog() {        // 程式碼區1      CDialog::OnInitDialog();     // 注:句1        // 程式碼區2} void dddd::OnSize(UINT nType, int

VC++在MFC呼叫EXCEL各種功能實現

一直以來就對EXCEL的各種功能很崇拜,後來經常使用VC,由於工作的需要,經常會遇到將文字檔案中的龐大資料提取到Excel中運算處理。這個工作量可謂是勞民傷財,但是又不可不做,於是使用最簡單的資料流(fscanf(), fprintf()之類)書寫文字格式的Excel檔案,其弱智程度我就不說了。。。 但是隨著

MFC對串列埠的操作以及定時器的呼叫

最近研究了一下MFC下對串列埠的操作,測試了一下對裝置的讀寫。 1.開啟串列埠 1 GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(FALSE); 2 m_hComm = CreateFile("COM1",

MFC:建立dll呼叫dll

一、建立dll檔案:1、開啟VS2010,新建Win32專案,如下圖所示:2、應用程式型別,選取DLL3、新增新類 DigitalProc,在標頭檔案 DigitalProc.h中新增如下程式碼:#if

Eclipse 將projectBuild Path中引用的jar包自己主動復制到WEB-INFlib目錄

技術分享 異常 pat building -1 選擇 否則 sem rop 在用用 Eclipse進行Java Web開發時,web應用中引用的jar須要復制到WEB-INF下的lib目錄下,否則常常出現ClassNotFound異常。 通過以下方法,能夠不用手動拷貝jar

Visual Studio 2017 動態鏈接庫(DLL /LIB) 靜態鏈接庫(LIB)的思考

imp 動態 -o ffffff library code mic mage .org 軟件工程方面能夠快速的發展,我相信源代碼重用起到了不可忽略的作用。在Linux平臺下就C++而言,有以so結尾的動態鏈接庫文件,也有以.a結尾的靜態連接庫文件,這

QT生成DLL呼叫DLL

使一個專案編譯生成DLL庫而不生成可執行檔案: 刪除main()函式; 將.pro專案檔案中的TEMPLATE = app改為TEMPLATE = lib。 然後編譯,此時生成的就是.a和.dll的檔案。 在另一個專案中呼叫此DLL: 在專案檔案中新

VS2013 MFCdll 多介面 引數傳遞 小雜記

目錄 1. char[] 轉變 cstring     2. 輸出字串到txt、MessageBox、T2A、_splitpath_s 3. CStringArray的使用、開啟對話方塊將選中的檔名讀出來,允許選擇多個檔案,注意檔名快取 4. 全域性

原始碼剖析 | 螞蟻金服 mPaaS 框架的 RPC 呼叫歷程

背景 mPaaS-RPC 是支付寶原生的 RPC 呼叫庫。 在客戶端開發過程中,只需要簡單的呼叫庫裡封裝的函式即可完成一次資料請求過程,但是遇到異常情況往往會面對各種異常碼卻不知所云。所以這篇文章帶領大家瞭解一下 mPaaS-RPC 的呼叫過程以及各種異常碼產生的原因。 1. 使用方法 在 Andro

windows c++ 如何呼叫 python 3

本文所使用環境: win10 (x64) +  VS2013 + python 3.5.2 (x64) python官網下載地址 一、先配置環境 1.安裝python 2.把 python 新增到VS2013     (1) VS新建一個空的Win3

C# C++ dll 相互呼叫文章彙總

====cpp呼叫cpp DLL  三件套(顯式 隱式)       利用C++製作dll並呼叫dll 顯式呼叫 https://blog.csdn.net/hlx371240/article/details/51507025   ====c

MFC子對話方塊呼叫主對話方塊的變數和函式

1、在子對話方塊中定義主對話方塊的物件指標: CSensorSysDlg *parent = (CSensorSysDlg*)GetParent();//CSensorSysDlg是主對話方塊對應的類 2、呼叫 //呼叫變數 parent->i;//i是主對話方塊內int型別的