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;
}

运行如下:
在这里插入图片描述

隐式导出和显式导出,隐式导入和显式导入,我们都可以混合使用!!

posted @ 2022-10-19 23:31  hugeYlh  阅读(69)  评论(0编辑  收藏  举报  来源