摘要百度百科的解释:
动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。这些库函数的扩展名是 ”.dll"、".ocx"(包含ActiveX控制的库)或者 “.drv”(旧式的系统驱动程序)。
动态链接库百度百科
对我们而言,知道 库文件 .dll 和 符号辅助文件.lib 就足够了。
直接切入主题:
如果你用的是 vs 那么可以直接创建c++空项目,然后修改一下项目属性,然后在制作无疑是最好的方式。
在Windows我个人喜欢用 Unicode字符。
接下来我们 添加一个 预处理定义
定义 DemoDll 宏
如果你定义了预处理宏的效果
编写c++ 兼容
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。
.h 头文件 基础代码框
#pragma once
#ifdef DemoDll
#define DemoDll_API __declspec(dllexport) // 导出
#else
#define DemoDll_API __declspec(dllimport) // 导入
#endif // DemoDll
/*
\ brief
__cplusplus c++宏
*/
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*
\ brief 在这里编写 函数模块
*/
#ifdef __cplusplus
}
#endif // __cplusplus
编写一个 add 函数
demo.h 文件代码
#pragma once
#ifdef DemoDll
#define DemoDll_API __declspec(dllexport) // 导出
#else
#define DemoDll_API __declspec(dllimport) // 导入
#endif // DemoDll
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*
\ brief 在这里编写 函数模块
*/
int DemoDll_API add(int a, int b);
#ifdef __cplusplus
}
#endif // __cplusplus
demo.cpp 文件代码
#include "demo.h"
int DemoDll_API add(int a, int b)
{
return a + b;
}
接着编译,完成之后打开项目的Debug目录查看 .dll 文件 和 .lib 文件
接下来我们新建一个空项目然后使用这个动态库
将demo.h 头文件 demo.dll 扩展名文件 demo.lib 链接库文件拷到项目下
将 demo.h 文件 和 demo.lib 文件 添加到项目中
接下来我们查看下 头文件,就可以理解之前编写动态库 添加预处理的宏的好处。
创建main.cpp 文件 进行测试
#include<iostream>
#include"demo.h"
using namespace std;
int main(int argc, char* argv[])
{
cout << " 4 + 6 = " << add(4, 6) << endl;
}
运行结果
你也可以这样连接到 .lib 文件
#include<iostream>
#include"demo.h"
using namespace std;
#pragma comment(lib, "DemoDll.lib")
int main(int argc, char* argv[])
{
cout << " 4 + 6 = " << add(4, 6) << endl;
}
对于一般人来说,这样的用法已经足够了。但是有一些人需要一些特别的用法。
接着我们继续改造 这个动态库
修改 demo.h 头文件 添加一个 动态库入口点函数,这个需要Windows 库支持
#pragma once
#include<Windows.h> // 引用Windows库
#ifdef DemoDll
#define DemoDll_API __declspec(dllexport) // 导出
#else
#define DemoDll_API __declspec(dllimport) // 导入
#endif // DemoDll
/*
\ brief 动态链接库(DLL)的可选入口点
\ param hinstDLL DLL模块的句柄,该值是DLL的基地址
\ param fdwReason 指示为什么调用DLL入口点函数的原因码
\ param lpvReserved 如果fdwReason是DLL_PROCESS_ATTACH,lpvReserved是NULL动态载荷和非NULL的静态载荷
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
/*
DLL入口点:
进程加载DLL (DLL_PROCESS_ATTACH)
当前进程创建一个新线程 (DLL_THREAD_ATTACH)
线程正常退出 (DLL_THREAD_DETACH)
进程卸载DLL (DLL_PROCESS_DETACH)
*/
switch (fdwReason)
{
// 进程加载DLL
case DLL_PROCESS_ATTACH:
MessageBoxW(NULL, TEXT("Hello word"), TEXT("Title"), NULL);
break;
// 当前进程创建一个新线程
case DLL_THREAD_ATTACH:
break;
// 线程正常退出
case DLL_THREAD_DETACH:
break;
// 进程卸载DLL
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*
\ brief 在这里编写 函数模块
*/
int DemoDll_API add(int a, int b);
#ifdef __cplusplus
}
#endif // __cplusplus
那么这个 DllMain() 这个 函数有什么用呢?
依旧是编译,生成动态库。
然后按照老规矩,将 .lib 和 .dll 文件 拷贝到项目中
接下来是项目代码
main.cpp
#include<iostream>
#include<Windows.h> // 引用Windows库
using namespace std;
/*
\ brief 定义一个函数指针别名
*/
typedef int (*ADD)(int, int);
int main(int argc, char* argv[])
{
// 使用LoadLibraryW()函数将 DemoDll库导入到项目中
HMODULE hModule = LoadLibraryW(TEXT("DemoDll.dll"));
if (hModule == NULL) {
return 0;
}
// 使用 GetProcAddress()函数 导出 add()函数的地址,赋值给 add指针变量中
ADD add = (ADD)GetProcAddress(hModule, "add");
if (add == NULL) {
return 0;
}
// 执行结果
cout << " 4 + 6 = " << add(4, 6) << endl;
// 释放动态库
FreeLibrary(hModule);
}
那么运行一下,
那么我们可以得出结论,当使用LoadLibraryW()函数 动态加载动态库的时候,
会调用DllMain()函数。
这样做有什么用呢?
这就得提到 ,远线程的动态库的注入技术了,这个有缘再讲。
接下来使用,vs 直接创建动态库项目
创建项目
名称
项目创建完成
至于framework.h 文件 与 pch.h pch.cpp 文件 自己看可以文件中的注释来理解如何使用、我就不多讲了。
文章时间2019年12月19日14:54:38