当前位置: 首页 > news >正文

编写并使用dll

第一部分:创建 DLL
步骤 1:创建新项目``

  1. 打开 Visual Studio 2022。
  2. 点击“创建新项目”。
  3. 在搜索框中,输入 dynamic,然后选择“动态链接库 (DLL)”模板。如果找不到,也可以选择“空项目”,然后手动配置。
  4. 点击“下一步”,为项目命名(例如 MyMathDLL),选择位置,然后点击“创建”。

步骤 2:编写 DLL 代码
DLL 需要明确指定哪些函数是可供外部程序(称为“客户端”)使用的。我们通过 __declspec(dllexport) 关键字来实现。
在“解决方案资源管理器”中,右键点击“源文件” -> “添加” -> “新建项...”,创建一个名为 mymath.c 的文件。
将以下代码写入 mymath.c
`#include <stdio.h>

// 声明函数为导出函数
// __declspec(dllexport) 是关键,它告诉编译器这个函数需要被导出
__declspec(dllexport) int add(int a, int b) {
return a + b;
}

__declspec(dllexport) int subtract(int a, int b) {
return a - b;
}

// 一个只在DLL内部使用的函数(辅助函数),不被导出
void internal_helper_function() {
printf("This is an internal function, not exported.\n");
}`

步骤 3:创建头文件(可选但强烈推荐)
为了让使用你 DLL 的程序员知道有哪些函数可用以及它们的参数,最好创建一个头文件。
右键点击“头文件” -> “添加” -> “新建项...”,创建一个名为 mymath.h 的文件。
将以下代码写入 mymath.h
`// mymath.h - DLL 的头文件

// 为了防止头文件被多次包含时重复定义

pragma once

ifdef __cplusplus

extern "C" { // 如果被C++程序使用,确保以C语言的方式编译和链接

endif

// 声明导出函数。
// 注意:这里用的是 `__declspec(dllexport)`,因为当前在编译DLL本身。
__declspec(dllexport) int add(int a, int b);
__declspec(dllexport) int subtract(int a, int b);

ifdef __cplusplus

}

endif`

步骤 4:生成 DLL

  1. 在顶部菜单栏,确保解决方案配置是“Release”和“x64”(或者 x86,根据你的目标平台选择,建议初学用 x64)。
  2. 点击“生成” -> “生成解决方案”。
  3. 如果成功,你会在项目目录下的 x64/Release/ 文件夹中找到两个重要文件:
    MyMathDLL.dll:这就是动态链接库本身,包含了编译后的二进制代码。
    MyMathDLL.lib:这是导入库,客户端程序在链接时需要这个文件。它包含了帮助程序找到DLL中函数的信息。

第二部分:创建客户端程序使用 DLL
现在,我们来创建另一个程序来调用刚刚生成的 DLL 中的函数。
方法一:隐式链接(最常用、最简单)
这种方法需要在编译时提供 .lib 文件,并在运行时需要 .dll 文件。
步骤 1:创建新的客户端项目

  1. 在当前的 Visual Studio 解决方案中:
    右键点击“解决方案 ‘MyMathDLL’” -> “添加” -> “新建项目”。
  2. 选择“控制台应用”模板,命名为 TestDLL,点击“下一步”创建。
  3. 确保新项目 TestDLL 也被设置为 Releasex64(与 DLL 项目保持一致)。
    步骤 2:配置客户端项目
    我们需要告诉客户端项目在哪里可以找到 DLL 的头文件和导入库(.lib)。
  4. 添加头文件路径:
    右键点击 TestDLL 项目 -> “属性”。
    在左侧,找到“C/C++” -> “常规”。
    在“附加包含目录”中,添加 mymath.h 所在的路径(即 DLL 项目的路径)。例如:..\MyMathDLL
  5. 添加导入库(.lib)路径和文件名:
    在属性页,找到“链接器” -> “常规”。
    在“附加库目录”中,添加 MyMathDLL.lib 所在的路径(即 x64/Release/)。例如:..\MyMathDLL\x64\Release
    找到“链接器” -> “输入”。
    在“附加依赖项”中,添加 MyMathDLL.lib
    步骤 3:编写客户端代码
    TestDLL 项目的源文件(如 TestDLL.c)中,写入以下代码:
    `// TestDLL.c - 客户端程序

// 包含DLL的头文件,这样我们就知道add和subtract函数的原型

include "mymath.h"

include <stdio.h>

int main() {
int a = 10, b = 5;

// 直接调用DLL中的函数,就像调用普通函数一样
int sum = add(a, b);
int difference = subtract(a, b);printf("a = %d, b = %d\n", a, b);
printf("a + b = %d\n", sum);
printf("a - b = %d\n", difference);return 0;

}`
步骤 4:运行客户端程序

  1. 右键点击 TestDLL 项目 -> “设为启动项目”。
  2. Ctrl + F5 运行。
  3. 重要:确保 MyMathDLL.dll 文件在客户端程序(TestDLL.exe)可以找到的地方。通常有几种方法:
    MyMathDLL.dll 复制到 TestDLL.exe 所在的目录(即 TestDLL\x64\Release\)。
    或者更简单:在 TestDLL 项目的“属性” -> “调试” -> “工作目录”中,设置为DLL所在的路径(..\MyMathDLL\x64\Release)。
    方法二:显式链接(更灵活,更复杂)
    这种方法在运行时通过 Windows API(LoadLibrary, GetProcAddress)手动加载 DLL 和获取函数地址,不需要 .lib 和头文件(但你需要知道函数的原型)。
    客户端代码示例(不需要配置链接器):
    `#include <windows.h>

include <stdio.h>

// 定义函数指针类型,必须与DLL中的函数原型完全匹配
typedef int(ADD_FUNC)(int, int);
typedef int(
SUBTRACT_FUNC)(int, int);

int main() {
HINSTANCE hDll;
ADD_FUNC add_func;
SUBTRACT_FUNC subtract_func;
int a = 10, b = 5;

// 1. 加载DLL
hDll = LoadLibrary(TEXT("MyMathDLL.dll"));
if (hDll == NULL) {printf("Failed to load DLL!\n");return 1;
}// 2. 获取函数地址
add_func = (ADD_FUNC)GetProcAddress(hDll, "add");
subtract_func = (SUBTRACT_FUNC)GetProcAddress(hDll, "subtract");if (add_func == NULL || subtract_func == NULL) {printf("Failed to get function address!\n");FreeLibrary(hDll);return 1;
}// 3. 使用函数
int sum = add_func(a, b);
int difference = subtract_func(a, b);printf("a = %d, b = %d\n", a, b);
printf("a + b = %d\n", sum);
printf("a - b = %d\n", difference);// 4. 卸载DLL
FreeLibrary(hDll);return 0;

}使用这种方法,你只需要确保MyMathDLL.dll在程序可找到的路径(如同一目录)即可,不需要.lib` 文件和头文件(在编译时)。
总结
屏幕截图 2025-12-28 213438
对于大多数情况,隐式链接是更直接和首选的方法。显式链接则在需要动态加载插件、处理不同版本DLL或需要更精细的错误控制时非常有用。

http://www.jsqmd.com/news/155781/

相关文章:

  • YOLOv10新增PGI辅助监督,梯度传播更充分
  • YOLO训练数据合成技术:用GAN生成更多样本
  • 专科生必看!8个高效降AIGC工具推荐,轻松应对AI检测
  • YOLO与RetinaNet对比评测:谁更适合你的业务场景?
  • YOLO目标检测支持HTTPS?SSL卸载+GPU加速
  • YOLO训练任务依赖管理:复杂Pipeline编排
  • 阿里面试:redisson分布式锁重入锁,为什么要有HINCRBY 自增 减一?
  • YOLO镜像提供API限流与熔断机制
  • 近期黄金和白银涨势和市场极端表现预示着什么?是否意味着纸币的黄昏和债权危机的表现?
  • YOLO目标检测与语音提示联动:无障碍交互设计
  • 阿里面试:延迟双删有什么问题?大厂是如何优雅避开 延迟双删 的?
  • Dify可视化界面对接PyTorch模型的服务化路径
  • 大数据领域数据服务的隐私保护措施
  • 数据科学与DevOps:构建自动化数据处理流水线
  • YOLO目标检测模型支持实时标注反馈吗?闭环训练系统上线
  • 《干货满满!提示工程架构师畅谈Agentic AI的社会影响实践经验》
  • Arduino驱动LED入门:项目应用完整指南
  • 金融市场未来演变会是什么样呢?你我普通人应该知道什么?准备什么?
  • YOLO目标检测在机场行李分拣系统的智能化升级
  • git报错:error: RPC failed; curl 55 Send failure: Connection fatal: the remote end hung up unexpectedly
  • PyTorch-CUDA-v2.6镜像安装教程:GPU加速深度学习训练全流程详解
  • YOLO在半导体晶圆检测中的亚微米级识别能力
  • Git下载慢影响效率?搭配国内镜像源加速AI环境搭建
  • 《运营商“换帅“暗藏玄机!工信部新成立委员会,AI+机器人万亿市场爆发在即》
  • YOLOv10新增Decoupled Head,精度提升的秘密
  • 数据服务与低代码平台:快速构建数据应用
  • 近期北方各地泉水复涌,是什么原因?地球变化了?还是像网上说的环保做的好?本质原因是什么?
  • YOLO模型训练日志归档策略:长期保存GPU运行记录
  • 清华镜像源加速PyTorch安装,配合CUDA环境更流畅
  • 第01章—开篇词:如何才能精通Redis?