【C++动态库】

1.vs2022 生成动态库dll

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

微软官方教程演练

cpp 复制代码
#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工具,可以在终端中用命令行调用。

bash 复制代码
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:

cpp 复制代码
#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;
}

但是显式加载需要知道函数的参数信息,需要了解开发文档或者反编译。但是反编译信息给的太少,还是需要开发文档。

补充知识:句柄是什么意思?

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

相关推荐
机器视觉知识推荐、就业指导2 小时前
面试问题详解五:Qt 信号与槽的动态管理
开发语言·qt
MZ_ZXD0014 小时前
springboot汽车租赁服务管理系统-计算机毕业设计源码58196
java·c++·spring boot·python·django·flask·php
岁忧6 小时前
(nice!!!)(LeetCode 每日一题) 679. 24 点游戏 (深度优先搜索)
java·c++·leetcode·游戏·go·深度优先
小欣加油6 小时前
leetcode 3 无重复字符的最长子串
c++·算法·leetcode
四维碎片8 小时前
【Qt】线程池与全局信号实现异步协作
开发语言·qt·ui·visual studio
IT码农-爱吃辣条8 小时前
Three.js 初级教程大全
开发语言·javascript·three.js
☺����9 小时前
实现自己的AI视频监控系统-第一章-视频拉流与解码2
开发语言·人工智能·python·音视频
zylyehuo9 小时前
C++基础编程
c++
染翰9 小时前
lua入门以及在Redis中的应用
开发语言·redis·lua
王者鳜錸9 小时前
PYTHON让繁琐的工作自动化-函数
开发语言·python·自动化