动态链接库(DLL)开发基础

本周我的博客涉及到动态链接库的基础开发。我在刚开始学习动态链接库的开发、在网上找DLL开发基础知识教程时发现网上的资料还是太杂,对初学者不太友好,于是我就着手写了这篇博客,本篇博客知识有DLL简介、DLL的两种制作方式、隐式调用显式调用两种调用方式以及最后的代码实例,编译器是VS2019。纯小白教学,希望能对刚入门的你有所帮助。最后,如果感觉文章还可以的话请一键三连哦。

DLL简介

动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库。动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此在发布和运行时需要相应DLL文件的支持。

优点:当程序使用 DLL 时,具有以下的优点: 使用较少的资源,当多个程序使用同一个函数库时,DLL
可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大大影响其他在 Windows
操作系统上运行的程序。 推广模块式体系结构DLL
有助于促进模块式程序的开发。这可以帮助您开发要求提供多个语言版本的大型程序或要求具有模块式体系结构的程序。模块式程序的一个示例是具有多个可以在运行时动态加载的模块的计帐程序。
简化部署和安装当 DLL 中的函数需要更新或修复时,部署和安装 DLL 不要求重新建立程序与该 DLL 的链接。此外,如果多个程序使用同一个
DLL,那么多个程序都将从该更新或修复中获益。

DLL的两种制作方法

使用_declspec方式创建动态库

1.打开vs2019,新建一个动态链接库,输入项目名称,点击创建。
在这里插入图片描述
在这里插入图片描述
2. 在头文件创建dll.h头文件,在源文件创建dll.cpp文件
在这里插入图片描述
3. 在dll.h和dll.cpp中各加入下列代码
dll.h

#ifdef BUILD_DLL
#define API_SYMBOL _declspec(dllexport)
#else
#define API_SYMBOL _declspec(dllimport)
#endif // BUILD_DLL

extern "C" API_SYMBOL int convert_array(int* data, int len);

dll.cpp
注意最开始加入头文件#include “pch.h”,否则会报错

#include "pch.h"
#include "dll.h"
#include <iostream>
using namespace std;

int convert_array(int* data, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << data[i] << ",";
	}
	cout << endl;

	int nTotal = 0;
	for (int i = 0; i < len; i++)
	{
		nTotal += data[i];
		--data[i];
	}
	return nTotal;
}

如图所示:
在这里插入图片描述
在这里插入图片描述
4. 右击项目DLL01,点击重新生成,当出现下面截图代表DLL生成成功。
在这里插入图片描述
5.打开相应目录,可发现生成的文件。
在这里插入图片描述

使用模块定义文件.def创建动态库

该方法相比于第一种方法简便很多。
1、2步同上
3. 创建dll.h文件,内容如下:

#pragma once
int convert_array(int* data, int len);

创建dll.cpp文件,文件内容同上dll.cpp.
截图如下:
在这里插入图片描述
在这里插入图片描述
4.创建.def文件
右击源文件-》添加-》新建项-》代码-》模板定义文件,点击添加
在这里插入图片描述
在模板定义文件中加入以下代码:

LIBRARY Dll02
EXPORTS
convert_array @1

其中Dll02、convert_array分别是项目名和函数名,可更改。有几个函数后面@几,按顺序加。如:

LIBRARY Dll
EXPORTS
convert_array @1
add @2
sub @3
  1. 右击项目DLL02,点击重新生成,当出现下面截图代表DLL生成成功。
    在这里插入图片描述
  2. 打开项目对应目录可发现已经生成相应的文件。
    在这里插入图片描述

DLL的两种调用方式

隐式调用

1.首先创建一个控制台应用。右击解决方案-》添加-》新建项目-》控制台应用,创建一个名为Isinvokedll的控制台应用。如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.在生成的Isinvokedll.cpp文件里声明头文件 #include “dll.h”,这时include会标红,因为这两个项目没在一个文件夹内,编译器不知道dll.h文件的位置,这时需要我们手动配置文件依赖。
右击Isinvokedll文件 -》属性 -》C/C++ -》附加包含目录。
在这里插入图片描述在这里插入图片描述
点击三个点,就会出现文件的路径,选择文件夹,确认,应用,确认。
在这里插入图片描述
3.然后include就不标红了。
此时再往头文件里加入

#pragma comment (lib,"Dll01.lib")

这是告诉编译器与该dll相对应的.lib文件所在的路径和文件名。在生成dll文件时,链接器会自动为其生成一个对应的.lib文件,该文件包含了dll导出函数的符号名和序号(并没有实际的代码)。在应用程序中,.lib文件将作为dll的替代文件参与编译,编译完成后,.lib文件就不需要了。
添加完后还需要配置该lib文件的附加库目录。与配置的dll.h文件类似。
右击项目—》属性—》链接器—》常规—》附加库目录,添加Dll01.lib的文件路径。
在这里插入图片描述

一般相对路径在项目文件的debug目录下,如下图所示:
在这里插入图片描述
4. 添加下列代码到Isinvokedll文件夹中

#include <iostream>
#include "dll.h"
#pragma comment (lib,"Dll01.lib")

int main()
{
    int arr[] = { 3,6,7,8 };
    int nLen = sizeof(arr) / sizeof(int);
    int nTotal = convert_array(arr, nLen);
    std::cout << "数组元素求和结果:" << nTotal << std::endl;
    std::cout << "数组元素新值:" << std::endl;
    for (int i = 0; i < nLen; i++)
    {
        std::cout << arr[i] << ",";
    }
}
  1. 右击项目,设为启动项,运行项目,如图所示,项目运行成功。
    在这里插入图片描述
    在这里插入图片描述

显式调用

显示调用不需要配置各种文件路径和附加库,大概分为5步,

  1. 声明头文件 #include <Windows.h>
  2. 创建一个别名,它引用的函数类型需要和dll中的导出函数一致。
  3. 加载DemoDll.dll动态库文件。
  4. 获取dll中函数的地址。
  5. 调用函数。
  6. 释放动态库句柄。

实例如下所示:

#include <iostream>
#include <Windows.h>

//第一步,创建一个别名,它引用的函数类型需要和dll中的导出函数一致。
typedef int (*LPDO_ARRAY)(int* pArr, int nlen);
int main()
{
    HINSTANCE hDll;//定义一个实例句柄,引用动态库;
    LPDO_ARRAY lpDo_array;//定义一个函数指针,用来指向导出函数

    //第二步,加载DemoDll.dll动态库文件
    hDll = LoadLibrary(L"Dll02.dll");
    if (hDll != NULL)
    {
        //第三步,获取dll中函数的地址
        lpDo_array = (LPDO_ARRAY)GetProcAddress(hDll, "convert_array");
        if (lpDo_array != NULL)
        {
            //第四步,调用函数
            int nArr[] = { 1,2,4,6 };
            int nlen = sizeof(nArr) / sizeof(int);
            int nRet;

            //通过函数指针lpDo_array调用函数
            nRet = lpDo_array(nArr, nlen);
            std::cout << "返回值:" << nRet << std::endl;
            std::cout << "数组新值: ";
            for (int i = 0; i < nlen; ++i)
            {
                std::cout << nArr[i] << ",";
            }
        }
        //第五步,释放动态库句柄
        FreeLibrary(hDll);
    }

}

运行截图:
在这里插入图片描述
over!

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值