創建靜態庫
然後直接創建一個.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副本的內容
利於升級
靜態庫優點
靜態庫代碼裝載速度快,不需要考慮用戶計算機上靜態庫文件是否存在