DLL动态链接库的导入导出
动态链接库英文DLL,是Dynamic Link Libarary的缩写。
Dll中包含若干公用的代码、数据等,可供其他模块(DLL或exe文件等)使用。
Dll中并不是所有的函数都必须供其他模块使用,只有经过 导出(export) 后才允许被外部正常调用。
动态库的由来:
Dll最初用于节约应用程序所需要的磁盘空间和内存空间。早前在传统的非共享库中,一部分代码简单的附加到调用的程序中。如果两个程序同时调用同一个子程序,就会出现两份代码。
动态链接库导出
创建一个动态链接库的项目:
显式导出
格式:
extern "C" _declspec(dllexport) function
导出实现:
/*
dllmain.cpp
*/
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
/*
在此写上函数的定义及实现
*/
int sum(int a, int b)
{
printf("sum");
return 0;
}
int Div(int a, int b)
{
printf("div");
return 0;
}
int mul(int a, int b)
{
printf("mul");
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
/*
pch.h 在此显式导出Dll
*/
extern "C" _declspec(dllexport)
int sum(int a, int b);
extern "C" _declspec(dllexport)
int Div(int a, int b);
extern "C" _declspec(dllexport)
int mul(int a, int b);
我们在一个主函数DllMain中将函数实现好,然后再从头文件中将函数利用extern ”C“导出
除了导出函数外,dll文件还可以导出变量,c++类。
隐式导出
我们无需使用extern ”C“导出,只需要创建一个新的名为export.def 的文件,然后在此文件中写上如下内容:
/*
export.def 文件
*/
LIBRARY "MyDll"
EXPORTS
sum @ 1 //函数名 @符号 函数的序号
Div @ 2
mul @ 3
- LIBRARY后面跟的是这个项目的名称!!
- EXPORTS,LIBRARY都是固定的格式
- 后面跟着导出函数的信息: 函数名 @ 你想指定的函数序号
注意:需要打开 项目–>属性–>链接器–>输入–>模块定义文件
然后把export.def 写进去。
表明依靠指定的模块即export.def,导出Dll动态库。
对于dll项目:编译器通常会产生两个文件,分别是.DLL .lib
- dll是动态链接库,保存了所有的代码和数据。
- lib是导入库,保存了一些符号和地址的对应信息。不能单独使用 必须与dll共存。,用于动态链接库的隐式链接。
动态链接库导入
显式导入
显示链接方式调用导出函数:
//加载dll动态库
HMODULE hModule = LoadLibraryW(L"mydll.dll");
//获取相应的函数
GetProcAddress(hModule,"");
FreeLibrary();
导入:
#include "main.h"
typedef int (*sum)(int a, int b);
typedef int (*Div)(int a, int b);
typedef int (*mul)(int a, int b);
int main()
{
//1. 载入DLL文件
HMODULE hModule = LoadLibraryW(L"MyDll.dll");
//2. 拿到要调用的函数
sum sumFunc;
Div DivFunc;
mul mulFunc;
if (hModule)
{
sumFunc = (sum)GetProcAddress(hModule, "sum");
printf("%d\n", sumFunc(1, 2));
DivFunc = (Div)GetProcAddress(hModule, "Div");
printf("%d\n", DivFunc(1, 2));
mulFunc = (mul)GetProcAddress(hModule, "mul");
printf("%d\n", mulFunc(1, 2));
}
}
注意:
- LoadLibrary 函数会加载DLL,并且返回一个HMODULE
- GetProcAddress函数会获得指定的函数,第一个参数为获得的HMUODULE,第二个参数为函数的名字,带“” 号。
- GetProcAddress的返回值为指定函数的指针,我们需要首先声明某个类型的函数指针,然后将此作为函数的返回值。
运行如下:
隐式导入
通过隐式链接的方式调dll导出的函数:
#pragma comment(lib,"xx.lib")
隐式导入:
/*
head文件
*/
#include <iostream>
#include <Windows.h>
#pragma comment(lib,"MyDll.lib")
extern "C" _declspec(dllimport)
int sum(int, int);
extern "C" _declspec(dllimport)
int mul(int, int);
extern "C" _declspec(dllimport)
int Div(int, int);
主函数:
int main()
{
printf("%d\n", mul(1, 2));
printf("%d\n", Div(1, 2));
printf("%d\n", sum(1, 2));
return 0;
}
运行如下:
隐式导出和显式导出,隐式导入和显式导入,我们都可以混合使用!!
本文来自博客园,作者:hugeYlh,转载请注明原文链接:https://www.cnblogs.com/helloylh/p/17209682.html