自学内容网 自学内容网

【C++动态库】

1.vs2022 生成动态库dll

要创建一个生成dll的工程,包含头文件和源文件。

微软官方教程演练

#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

宏定义中的意思记录一下:
如果是打包输出MATHLIBRARY,那么久dllexport,否则dllimport。

#ifdef MATHLIBRARY_EXPORTS 到 #endif:这部分代码定义了一个宏MATHLIBRARY_API,它根据是否定义了MATHLIBRARY_EXPORTS宏来决定是导出(__declspec(dllexport))还是导入(__declspec(dllimport))函数。当你在创建DLL时,应该定义MATHLIBRARY_EXPORTS,这样函数就会被导出。如果你在另一个项目中使用这个DLL,不应该定义MATHLIBRARY_EXPORTS,这样函数就会被导入。

之后就是点击生成按钮,会在本地文件中找到dll库。

2.从外部查看dll内容

用到的是VS自带的dumpbin.exe工具,可以在终端中用命令行调用。

PS D:\cpp\dll_demo\Dll1\x64\Release> dumpbin.exe /exports .\Dll1.dll
Microsoft (R) COFF/PE Dumper Version 14.40.33811.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file .\Dll1.dll

File Type: DLL

  Section contains the following exports for Dll1.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           4 number of functions
           4 number of names

    ordinal hint RVA      name

          1    0 00001080 fibonacci_current = fibonacci_current
          2    1 00001090 fibonacci_index = fibonacci_index
          3    2 00001010 fibonacci_init = fibonacci_init
          4    3 00001030 fibonacci_next = fibonacci_next

  Summary

        1000 .data
        1000 .pdata
        1000 .rdata
        1000 .reloc
        1000 .rsrc
        1000 .text

3.DLL隐式加载

隐式加载:需要头文件、lib链接文件和dll库文件。分别负责找声明、编译链接和运行链接。
分三步:
1.属性–>C/C++ --> 附加包含目录中:写入头文件的文件路径。
2.链接器–>输入:写入dll的导入库lib。
3.连接器–>常规:附加库目录。

困扰多年的问题,补充知识:Visual Studio中C++的包含目录、附加包含目录和库目录和附加库目录的区别

4.DLL显式加载

显式加载:只需要dll库文件,公司只给了这个…不可能把源代码和lib给你的。

只需要三步(在代码中实现):
1.加载库文件:HMODULE hModule = LoadLibrary(L"xxxx.dll");
2.将内部的函数传递到函数指针:GetProcAddress();
3.销毁:FreeLibrary(hModule);

案例是继续上述微软教程实现的Demo:

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

typedef void (*FIB_INIT) (const unsigned long long a, const unsigned long long b);
typedef bool (*FIB_NEXT) ();
typedef unsigned long long (*FIB_CURRENT) ();
typedef unsigned (*FIB_INDEX) ();

int main()
{
HMODULE hModule = LoadLibrary(L"..\\..\\MathLibrary\\x64\\Debug\\MathLibrary.dll");
if (hModule == NULL) {
std::cerr << "加载失败" << std::endl;
return 1;
}

FIB_INIT fibInit = (FIB_INIT)GetProcAddress(hModule, "fibonacci_init");
FIB_NEXT fibNext = (FIB_NEXT)GetProcAddress(hModule, "fibonacci_next");
FIB_CURRENT fibCurrent = (FIB_CURRENT)GetProcAddress(hModule, "fibonacci_current");
FIB_INDEX fibIndex = (FIB_INDEX)GetProcAddress(hModule, "fibonacci_index");

if (!fibInit || !fibNext || !fibCurrent || !fibIndex) {
std::cerr << "无法加载函数" << std::endl;
return 1;
}

fibInit(1, 1);
// 生成序列中的下一个值
bool success = true;
unsigned index = 0;
do {
success = fibNext();
if (success) {
std::cout << "F(" << fibIndex() << ") = " << fibCurrent() << std::endl;
}
} while (success && index++ < 10); // 限制输出以避免无限循环
FreeLibrary(hModule);

return 0;
}

在这里插入图片描述
但是显式加载需要知道函数的参数信息,需要了解开发文档或者反编译。但是反编译信息给的太少,还是需要开发文档。

补充知识:句柄是什么意思?
句柄是一个值,标识系统中的一个资源,它是一个索引值,操作系统使用这个值来查找实际的资源。类似指针但是不暴露内存,更多是控制访问。


原文地址:https://blog.csdn.net/qq_45306739/article/details/142911825

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!