C++:动态库的创建与调用——def文件

本文详细介绍了动态库DLL的两种创建方法,包括不使用.def文件和使用.def文件的方式,并提供了具体示例。同时,讲解了动态库的隐式调用与显式调用方法,以及.def文件的使用技巧。

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

动态库的创建有两种方法:不使用.def的方法 和 使用.def的方法;

示例:

写个简单的动态库,里面有两个函数,能实现加法减法

s1: 创建一个空动态库dll, 新建头文件sss.h, 在头文件中写入如下代码

s2: 再创建源文件sss.cpp, 如下:

s3: 新建模块定义文件Source.def,写入如下内容;

s4: 生成动态库DLL;

【注】:

在.def中第一行是数据库的名字,

第二行是固定语句EXPORTS,导出代码,

其他行,add、sub后面可以不加@X;

调用:

1.隐式调用

在同一解决方案下创建空WIN32控制台项目,在源文件中创建main.cpp,其代码如下

注意:隐式调用需要用到动态库里的头文件和动态库文件夹debug里的sss.lib,所以.cpp文件夹中一定要包含,可以拷贝两者到.cpp同一文件夹下,也可以用代码中的方法.

2. 显式调用

在同一解决方案下创建WIN32控制台空项目,在源文件中创建,代码如下

在显式调用中,由于使用的是.def的方法,在获取动态库中函数地址时有两种方法

①AddFunc ADD1 = (AddFunc)GetProcAddress(hdll,(char*)(1));

这是在.def文件中add后面加@1的使用方法,

当然你也可以使用通用获取地址方法:

②AddFunc ADD1 = (AddFunc)GetProcAddress(hdll,"add");

AddFunc ADD1 = (AddFunc)GetProcAddress(hdll,(char*)(1));这句(char*)(1)中1是add后面@的数字,相当于add在动态库中的地址,GetProcAddress的函数原型里1这个位置数据类型是char*类型.

附.def的一些小知识:

.def 文件中的第一条 LIBRARY 语句不是必须的,

但LIBRARY 语句后面的 DLL 的名称必须正确,即与生成的动态链接库的名称必须匹配。

此语句将 .def 文件标识为属于 DLL。

链接器将此名称放到 DLL 的导入库中。
EXPORTS 语句列出名称,可能的话还会列出 DLL 导出函数的序号值。通过在函数名的后面加上 @ 符和一个数字,给函数分配序号值。当指定序号值时,序号值的范围必须是从 1 到 N,其中 N 是 DLL 导出函数的个数。
LIBRARY BTREE
EXPORTS
Insert @1
Delete @2
Member @3
Min @4
“def   文件中的注释由每个注释行开始处的分号   (;)   指定。

注释不能与语句共享一行,但可以在多行语句的规范间出现。

 

参考文章

1. https://blog.csdn.net/qq_37059136/article/details/80167388

### DEF 文件格式定义使用方法 #### 什么是 DEF 文件DEF 文件是一种模块定义文件,它为链接器提供了关于被链接程序的导出、属性以及其他方面的信息。当生成动态链接库 (DLL) 或其他类型的可执行文件时,这种文件非常有用[^3]。 --- #### DEF 文件的内容结构 DEF 文件的主要内容分为以下几个部分: 1. **LIBRARY 声明** - 这是一个必填项,用于指定要创建的 DLL 的名称。 - 示例: ```plaintext LIBRARY MyLibrary ``` 2. **EXPORTS 部分** - 列出了需要从 DLL 中导出的所有函数或变量。 - 每个条目可以附加一个序号(OPTIONAL),以便通过序号访问导出的符号。 - 示例: ```plaintext EXPORTS FunctionA @1 FunctionB=AliasForFunctionB @2 NONAME FunctionC DATA ``` 上述示例中: - `FunctionA` 导出并分配了一个序号 `@1`。 - `FunctionB` 是其别名 `AliasForFunctionB` 并禁用了名字导入 (`NONAME`)。 - `FunctionC` 表示这是一个数据导出而非代码导出。 3. **SECTIONS 和 VERSION 可选声明** - 如果需要自定义内存节或者设置版本信息,可以在 DEF 文件中加入这些字段。 - 示例: ```plaintext SECTIONS .text READONLY VERSION 1.0 ``` --- #### 如何使用 DEF 文件? ##### 场景一:解决 C++ 名字修饰问题 在跨语言调用 DLL 库的情况下,如果仅依赖于 `extern "C"` 来防止 C++ 编译器的名字修饰功能,则可能无法完全解决问题。此时可以通过 DEF 文件显式地控制哪些符号应该被导出[^2]。 - 步骤说明: 1. 创建一个 `.def` 文件,并按照上述格式填写相关内容。 2. 将该 `.def` 文件传递给编译工具链中的链接阶段。 - 示例命令行配置(假设使用 MSVC 工具链): ```cmd cl /LD mysource.cpp /link /DEF:mylib.def ``` ##### 场景二:替代 __declspec(dllexport) 虽然可以直接在源码中标记 `__declspec(dllexport)` 关键字来指示导出特定符号,但在某些情况下(比如维护多个平台兼容性时),采用 DEF 文件会更加灵活和清晰。 --- #### Python 中的相关概念对比 尽管这里讨论的是 Windows 下的 DEF 文件及其用途,但值得一提的是,在 Python 中也有类似的机制用来描述函数签名——即 `def` 关键字所定义的函数以及它们如何处理参数[^4]。不过两者之间并无直接关联;一个是操作系统层面的技术细节,另一个则是高级脚本语言内部实现的一部分。 ```python # Python 函数定义示例 def example_function(param1, param2=None): """This is a simple function.""" if isinstance(param1, list): # 参数作为对象引用 param1.append('modified') elif type(param2).__name__ == 'int': # 类型检查 return param2 * 2 ``` --- #### 总结 综上所述,DEF 文件对于开发人员来说是非常重要的资源之一,尤其是在涉及复杂项目构建流程的时候。合理运用它可以有效简化工作量并提高效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值