win32 靜態庫和動態庫的使用

創建靜態庫

然後直接創建一個.h文件一個.cpp文件實現靜態庫中功能

libTest.c

#pragma once
extern int num;
int Add(int a, int b);

libTest.cpp

#include "libTest.h"
int num = 100;
int Add(int a, int b)
{
	return a + b;
}

然後直接運行就會在debug生成文件夾中有一個.lib文件

如何使用靜態庫?

將靜態庫中的.h文件一個生成的.lib文件拷貝到要使用的工程文件中

將靜態庫使用的.h文件添加到項目中

使用靜態庫

#include "stdafx.h"
#include <stdio.h>

#include "libTest.h"     //靜態庫頭文件
#pragma comment(lib,"靜態庫.lib")    //包含靜態庫

int main()
{
	printf("num=%d\n", num);             //使用靜態庫中的全局變量
	printf("Add(1,2)=%d\n",Add(1,2));    //使用靜態庫中函數
	

	getchar();
    return 0;
}

動態庫

創建方法同創建靜態,靜態庫改爲DLL

編寫動態庫代碼

DllTest.h

#pragma once
//在動態庫中的全局變量是不能被使用的(無法解析的外部符號)
extern _declspec(dllexport) int num;
//使用動態庫需要加上_declspec(dllexport) 只要保證在函數前面就可以 
//函數錢還需要加上extern "C" 防止C++改變函數名的問題
extern "C" _declspec(dllexport) int Add(int a, int b);

//動態庫中使用類注意事項:
//需要在類前面加上 _declspec(dllexport) 或者在成員函數名前加上_declspec(dllexport) 
//這兩種方式任選其一都ok,不然就是無法解析的外部符號

//☆☆☆☆☆最關鍵的☆☆☆☆☆
//使用動態庫中的類只能通過隱式調用的方式(也就是#pragma comment(lib,"動態庫.lib"))
//使用顯示調用(LoadLibrary())的方式是不可以的,都是無法解析的外部符號,即使是通過函數返回類指針對象之後
//使用該指針調用類的成員函數同樣是無法解析的外部符號
class A;
extern "C" _declspec(dllexport) A* CreateA(); 

class _declspec(dllexport)A										//在類名前加 _declspec(dllexport)
{
public:
	int Multi(int a, int b);				 //或者在成員函數前加 _declspec(dllexport)
};

DllTest.cpp

#include "stdafx.h"
#include "DllTest.h"
#include <iostream>
using std::nothrow;

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

A* CreateA()
{
	A* pA = new(nothrow) A();
	if (pA == NULL)
	{
		printf("實例化對象失敗\n");
	}
	return pA;
}

int A::Multi(int a, int b)
{
	return a*b;
}

 

使用動態庫

編譯之後將生成的.dll文件、.lib文件以及使用的.h文件拷貝到使用的項目中,將頭文件添加至工程

隱式調用動態庫

需要.dll動態庫文件、.lib導入庫文件

//隱示調用方式使用動態庫
//就很簡單了.在生成DLL的時候.會對應生成lib.我們直接使用這個lib即可.跟直接使用靜態lib庫一樣.
//但是需要注意我們也需要DLL
//這個lib庫只是輔助信息.並不跟上面你的靜態庫lib一樣.上面的靜態庫lib裏面是有實質性的代碼的.
#include "stdafx.h"
#include "DllTest.h"
#pragma comment(lib,"動態庫.lib")
#include <stdio.h>

int main()
{
	//printf("num=%d\n",num);				//不能使用動態庫中的全局變量
	printf("Add(1,2)=%d\n", Add(1, 2));		//使用動態庫中的函數
	A a;									//使用動態庫中的類
	printf("%d\n", a.Multi(2, 3));	

	A* pA = CreateA();						//使用動態庫函數中創建的類對象
	printf("%d\n", pA->Multi(3, 4));
	getchar();
    return 0;
}

顯示調用動態庫(不能使用類)

只有.dll動態庫文件就可以了

//顯示方式調用使用動態庫
#include "stdafx.h"
#include "DllTest.h"
#include <stdio.h>
#include <Windows.h>

typedef int(*pAddFun)(int, int);
typedef A* (*pCreateFun)();
int main()
{
	//加載動態庫
	HMODULE hModule = LoadLibrary(L"動態庫.dll");
	//獲取動態庫中的函數指針
	pAddFun pAdd = (pAddFun)GetProcAddress(hModule, "Add");
	printf("Add(1,2)=%d\n", pAdd(1, 2));	//或者使用 (*pAdd)(1,2)也是一樣的
	
	//不能使用類,無法解析的外部符號
	//pCreateFun pCreate = (pCreateFun)GetProcAddress(hModule, "CreateA");
	//A* pA = pCreate();
	//printf("a.Multi(2, 3)=%d\n", pA->Multi(2, 3));
	getchar();
	return 0;
}

靜態庫和動態庫的區別

靜態庫在彙編的時候將代碼和exe文件聯繫起來,所以會導致生成的exe文件增大,鏈接之後可以將.lib的靜態庫文件刪除了

動態庫只是在需要的時候進行調用動態庫中的內容,不會導致exe文件增大,但是在工程目錄中要一直保留使用的動態庫文件

動態庫一般會有對應的導入庫(.lib文件),方便程序靜態載入動態鏈接庫,如何沒有導入庫的話,那麼只能通過顯示調用的方式使用動態庫了,自己加載動態庫LoadLibrary(),自己獲取動態庫中的函數地址GetProcAddress()

有了導入庫,只需要鏈接導入庫後,按照頭文件中的函數聲明調用就可以了

導入庫和靜態庫的區別

靜態庫包含了實際執行代碼 、符號表等

導入庫只有符號表地址這些了,保證程序找到對應函數的一些基本地址信息,代碼是在動態庫中的

動態庫優點

DLL有助於共享數據和資源,多個應用程序可同時訪問內存中DLL副本的內容

利於升級

靜態庫優點

靜態庫代碼裝載速度快,不需要考慮用戶計算機上靜態庫文件是否存在

 

發佈了48 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章