天天看點

VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

VS2017建立DLL動态連結庫,并隐式與顯式調用

文章目錄

  • VS2017建立DLL動态連結庫,并隐式與顯式調用
  • 一、DLL基礎知識
  • 二、VS2017生成dll
    • 1.建立空白項目,建立.h頭檔案MyDLL.h
    • 2.編寫對應的c++檔案MyDLL.cpp
    • 3.修改配置,将預設生成exe改成生成dll
  • 三、 隐式調用dll檔案
    • 1 新建立空白項目,将上一步生成的.lib,.dll以及MyDLL.h均拷貝到目前項目檔案夾下
    • 2.編寫代碼,隐式調用dll 不要忘記#include "MyDLL.h"頭檔案
    • 3、顯式調用dll

一、DLL基礎知識

動态連結庫(dynamic-link library,DLL),Windows應用程式程式設計接口(API)提供的所有函數都包含在DLL中。其中三個最重要的DLL分别是:Kernel32.dll,包含的函數用來管理記憶體、程序以及線程;User32.dll,包含的函數用來執行與使用者界面相關的任務,如建立視窗和發送消息;GDI32.dll,包含的函數用來繪制圖像和顯示文字。著名的ActiveX技術也是基于這種運作時加載機制實作的。

Winows下的DLL檔案和EXE檔案實際上是一個概念,它們都是PE格式的二進制檔案,稍微有些不同的是PE檔案頭部中有個符号位表示該檔案是EXE或是DLL。需要通過在連結開關進行控制,來告訴編譯器編譯成DLL或者EXE。

DLL通常由一組可供任何應用程式使用的獨立函數組成。在DLL中,通常沒有用來處理消息循環或建立視窗的代碼。DLL隻不過是一組源代碼子產品,每個子產品包含一些可供應用程式(可執行檔案)或其他DLL調用的函數。

二、VS2017生成dll

1.建立空白項目,建立.h頭檔案MyDLL.h

代碼如下):

#pragma once

// 使用__declspec(dllexport)告訴編譯器我們對外暴露的函數以及全局變量
__declspec(dllexport) int ans = 10;
__declspec(dllexport) int Add(int, int);
           

2.編寫對應的c++檔案MyDLL.cpp

代碼如下(示例):

#include"MyDLL.h"

int Add(int a, int b) {
	ans = a + b;
	return ans;
}
           

3.修改配置,将預設生成exe改成生成dll

右鍵項目->屬性->正常->配置類型改成動态庫dll

VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

右鍵生成,即可生成dll檔案,同時還有符号表檔案.lib檔案(如果連結器檢測到DLL的源檔案輸出了至少一個函數或變量,那麼連結器還會産生一個.lib檔案。這個.lib檔案非常小,它隻是列出了所有被導出的函數和變量的符号名。為了建構可執行子產品,這個檔案時必須的。)

VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

三、 隐式調用dll檔案

vs隐式調用dll檔案十分簡單

1 新建立空白項目,将上一步生成的.lib,.dll以及MyDLL.h均拷貝到目前項目檔案夾下

VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

2.編寫代碼,隐式調用dll 不要忘記#include "MyDLL.h"頭檔案

靜态調用方式的特點是由編譯系統完成對DLL的加載和應用程式結束時DLL的解除安裝。當調用某DLL的應用程式結束時,若系統中還有其它程式使用該DLL,則Windows對DLL的應用記錄減,直到所有使用該DLL的程式都結束時才釋放它。靜态調用方式簡單實用,但不如動态調用方式靈活。

靜态調用方式不再需要使用系統API來加載、解除安裝DLL以及擷取DLL中導出函數的位址。這是因為,當程式員通過靜态連結方式編譯生成應用程式時,應用程式中調用的與.lib檔案中導出符号相比對的函數符号将進入到生成的EXE 檔案中,.lib檔案中所包含的與之對應的DLL檔案的檔案名也被編譯器存儲在EXE檔案内部。當應用程式運作過程中需要加載DLL檔案時,Windows将根據這些資訊發現并加載DLL,然後通過符号名實作對DLL 函數的動态連結。這樣,EXE将能直接通過函數名調用DLL的輸出函數,就像調用程式内部的其他函數一樣。

(必須把DLL工程的.h, .lib, .dll檔案放在EXE工程檔案夾下):

#include"MyDLL.h"
#include<iostream>
using namespace std;

int main() {

	int c = Add(10, 5);
	cout << "Add():" << c << endl;
	cout << "ans:" << ans << endl;
	system("pause");
	return 0;
}
           

運作即可調用DLL

VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

3、顯式調用dll

可以讓程式自己在運作時控制加載指定的子產品,并且可以在不需要該子產品時将其解除安裝。當程式需要用到某個插件或者驅動的時候,才将相應的子產品裝載進來,而不需要從一開始就将他們全部裝載進來,進而減少了程式啟動時間和記憶體的使用。

#include <windows.h>
#include <iostream>
//顯示調用DLL (運作時加載)

typedef int(*lpAddFun) (int, int);
using namespace std;
//需要使用系統API來加載、解除安裝DLL以及擷取DLL中導出函數的位址。
int main(int argc, char* argv[])
{
	HINSTANCE hDll; //DLL句柄
	lpAddFun addFun; //函數指針
//程序中的每個DLL子產品被全局唯一的位元組的HINSTANCE句柄辨別,隻有
//在特定的程序内部有效,句柄代表了DLL子產品在程序虛拟空間中的起始位址
	hDll = LoadLibrary("CreateDLL.dll");
	//(用來裝載一個DLL到程序的位址空間)
	if (hDll != NULL)
	{
		cout << "dLL 加載成功" << endl;
		//(用來查找某個符号的位址)
				//addFun = (lpAddFun)GetProcAddress(hDll, "Add");
		addFun = (lpAddFun)GetProcAddress(hDll,MAKEINTRESOURCE(1));
		if (addFun != NULL)
		{
			int result = addFun(2, 3);
			std::cout << "addFun(2, 3) = " << result << std::endl;
		}
		else {
			cout << "函數加載失敗" << endl;
		}
		FreeLibrary(hDll); //(用來解除安裝某個已加載的子產品)
	}
	system("pause");
	return 0;
}
           
VS2017建立DLL動态連結庫,并隐式與顯式調用VS2017建立DLL動态連結庫,并隐式與顯式調用一、DLL基礎知識二、VS2017生成dll三、 隐式調用dll檔案

繼續閱讀