C++ dll動態程式庫建置架構筆記(CMake build) -2 如何使用dll程式
這篇介紹如何讀取及使用 C++ 動態程式庫。
我的系統環境:
- Win10
- CMake 3.18.4
- VisualStudio 2019
一、介紹做法
我所知道的有兩種做法:
1.需要header、lib檔
優點:程式碼較少、不用重寫定義
缺點:還不知道
2.只需要dll檔
優點:可在程式執行中期匯入及釋放
缺點:程式碼較繁瑣、使用的人要知道 dll 裡面的 function 名稱及參數架構
二、說明
作法一、需要header、lib檔
需要 include
dll 程式提供給外部使用的 function 定義檔,也就是有加 __declspec(dllexport) 的部分。
以下是使用上一篇文章所做出來的 dll 程式。
test.cpp
#include <stdio.h> #include "my_math.h" int main() { int a = 10; int b = 20; int res = Add(a,b); printf("Add %d\n", res); res = Subtraction(a,b); printf("Subtraction %d\n", res); res = Multiply(a,b); printf("Multiply %d\n", res); math_class math_cls; res = math_cls.Add(a,b); printf("math_class Add %d\n", res); res = math_cls.Subtraction(a,b); printf("math_class Subtraction %d\n", res); res = math_cls.Multiply(a,b); printf("math_class Multiply %d\n", res); return 0; }
CMakeLists.txt
set (THE_MODULE "Dll_1Layer_main") set (Lib_project "Dll_1Layer_math") # connect Dll_1Layer_math.lib # include header INCLUDE_DIRECTORIES(../math/include) # output Dll_1Layer_main.exe ADD_EXECUTABLE(${THE_MODULE} test.cpp) TARGET_LINK_LIBRARIES(${THE_MODULE} ${Lib_project})
TARGET_LINK_LIBRARIES(${THE_MODULE} ${Lib_project})
這行的意思是告訴 CMake 連接 dll 專案"Dll_1Layer_math"。
作法二、只需要dll檔
這個做法使用 LoadLibraryA()
匯入 dll 檔,要先定義好 dll 裡面 function 架構,大小寫都不能錯,再讀入這個 function 的 memory
address,之後才能使用這個 function。
這個做法使用完要釋放掉,有個優點,能在程式執行中釋放掉 dll 程式,不暫記憶體,但是寫起來很痛苦,程式碼很多。
舉例如下:
function 架構: typedef int(*Add)(int a, int b);
function 架構: typedef int(*Add)(int a, int b);
讀入 memory address:add = (Add)GetProcAddress(hLib, "Add");
釋放掉 dll 程式:FreeLibrary(hLib);
test_withoutLib.cpp
#include <stdio.h>
#include <windows.h>
struct My_math_dll
{
private:
HMODULE hLib;
bool enable = false;
public:
//定義每個 function 原始的架構
typedef int(*Add)(int a, int b);
typedef int(*Subtraction)(int a, int b);
typedef int(*Multiply)(int a, int b);
typedef int(*Divided)(int a, int b);
typedef int(*Squared)(int a, int b);
//宣告 function 在這邊使用時的名稱
Add add;
Subtraction subtraction;
Multiply multiply;
Divided divided;
Squared squared;
~My_math_dll()
{
release();
}
int loadAPI()
{
// 讀入 dll
hLib = LoadLibraryA("Dll_1Layer_math.dll");
// If the dll file fails, the memory address will be 0.
printf_s("Dll_1Layer_math.dll address:%p\n", hLib);
if (!hLib)
{
printf_s("load Dll_1Layer_math.dll fail!\n");
return 0;
}
// 將每個 function 的 address 讀入
add = (Add)GetProcAddress(hLib, "Add");
subtraction = (Subtraction)GetProcAddress(hLib, "Subtraction");
multiply = (Multiply)GetProcAddress(hLib, "Multiply");
divided = (Divided)GetProcAddress(hLib, "Divided");
squared = (Squared)GetProcAddress(hLib, "Squared");
// Check the memory address obtained by the function API.
// If the function API fails, the memory address will be 0.
printf_s("API address: %p %p\n", add, subtraction);
enable = true;
return 0;
}
void release()
{
if (enable)
{
FreeLibrary(hLib);
enable = false;
}
}
};
int main()
{
My_math_dll mydll;
mydll.loadAPI();
int a = 10;
int b = 20;
int res = mydll.add(a,b);
printf("Add %d\n", res);
res = mydll.subtraction(a,b);
printf("Subtraction %d\n", res);
res = mydll.multiply(a,b);
printf("Multiply %d\n", res);
return 0;
}
CMakeLists.txt
set (THE_MODULE "Dll_1Layer_main_withoutLib") # output Dll_1Layer_main_withoutLib.exe ADD_EXECUTABLE(${THE_MODULE} test_withoutLib.cpp)
這就不用連接dll,因為要等程式執行到 LoadLibraryA() 才會匯入dll檔
留言
張貼留言