动态链接库的使用

本文详细介绍了如何在C++环境下创建动态链接库(DLL),包括生成DLL模块、使用extern关键字、编译生成.lib和.dll文件。同时,探讨了DLL的调用方式,如隐含链接和显式链接,并提到了.def文件在不同编译器间交互时的作用。此外,还讨论了extern "C"在C++和C混合编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创建DLL模块

1、生成代码:通过VS2019 创建新项目,选择项目模板“具有导出项的(DLL)动态链接库”,项目名称MyLib。生成的项目中包含以项目名称命名的MyLib.h和MyLib.cpp文件如下。

1)MyLib.h头文件

// 下列 ifdef 块是创建使从 DLL 导出更简单的

// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MYLIB_EXPORTS

// 符号编译的。在使用此 DLL 的

// 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将

// MYLIB_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的

// 符号视为是被导出的。

#ifdef MYLIB_EXPORTS

#define MYLIB_API __declspec(dllexport)

#else

#define MYLIB_API __declspec(dllimport)

#endif

// 此类是从 dll 导出的

class MYLIB_API CMyLib {

public:

CMyLib(void);

// TODO: 在此处添加方法。

};

extern MYLIB_API int nMyLib;

MYLIB_API int fnMyLib(void);

该文件注释中强调,DLL模块编译时需要定义宏MYLIB_EXPORTS,使用DLL的模块不需要定义这个宏。项目中自动创建的宏与项目名称相关,没有必要再去自定义。

通过宏来切换这里提到的类、变量和函数的输入和输出。DLL模块中定义宏,表示输出;使用DLL时,包含上述头文件,不再定义宏,表示输入。

2)MyLib.cpp文件

// MyLib.cpp : 定义 DLL 的导出函数。

//

#include "pch.h"

#include "framework.h"

#include "MyLib.h"

// 这是导出变量的一个示例

MYLIB_API int nMyLib=0;

// 这是导出函数的一个示例。

MYLIB_API int fnMyLib(void)

{

    return 0;

}

// 这是已导出类的构造函数。

CMyLib::CMyLib()

{

    return;

}

源代码文件程序的编写,与编写可执行程序没有差别。

2、编译:编译项目后生成.lib文件和.dll文件。

DLL模块提供给调用方的内容包含三个部分:.h头文件 .lib文件 .dll文件。

3、extern

在MyLib.h头文件中,关键字extern用在输出变量前面,用于声明一个外部变量。变量nMyLib在DLL模块的MyLib.cpp中被声明和定义。当调用方Include DLL模块的MyLib.h文件时,nMylib就可以作为外部变量来使用了。而类和函数前面并没有使用extern,这是因为它们默认就是外部声明。

经常在DLL模块的头文件中见到extern “C”的用法。形如,

#ifdef MYLIB_EXPORTS

#define MYLIB_API extern "C" __declspec(dllexport)

#else

#define MYLIB_API extern "C" __declspec(dllimport)

#endif

此类是从 dll 导出的

//class MYLIB_API CMyLib {

//public:

// CMyLib(void);

// // TODO: 在此处添加方法。

//};

MYLIB_API int nMyLib;

MYLIB_API int fnMyLib(void);

当进行C和C++混合编程时,才使用修改符extern “C”。并且,只在C++代码中使用,而不是在C代码中使用。使用了修改符号后,C++编码生成的DLL模块才能够被C、C++或任何其他语言调用。

代码中已经将类CMyLib注释掉了,修改符extern “C”作用在类上会报错,这是因为修改符无法让C++中的类被C调用。

二、创建可执行模块

可执行模块调用DLL模块有2种方式:加载时的隐含链接和运行期的显式链接。

1、隐含链接

1)调用模块编译时:包含MyLib.h头文件,添加#program comment(lib,MyLib.lib)

2)调用模块运行时:将MyLib.dll拷贝到调用方的执行目录下; 

2、显式链接

显式链接通过LoadLibrary函数实现。

三、其他

1、.def文件

如果使用Microsoft Visual Studio来创建DLL和使用该DLL的可执行模块,可以忽略.def文件。如果使用Microsoft Visual Studio创建DLL被其他编译器供应商创建的可执行模块时,需要使用.def文件。

.def文件定义了Microsoft Visual Studio创建的DLL模块中函数的输出名。当DLL模块中的函数使用__stdcall(WINAPI)调用规则时,编译后会改变函数的名字,而.def文件会告诉Microsoft的编译器不要改变函数名。形如,

LIBRARY

EXPORTS

        fnMyLib

四、参考

extern和extern "C"_lv_Amelia的博客-优快云博客

《Windows核心编程》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值