为什么从 .dll 导入函数时需要 .lib 文件?

2024-01-30

你能帮我理解,为什么从 dll 导入函数和数据时需要 .lib 文件吗?

我听说它包含来自相应 dll 的导出函数和数据元素的列表,但是当我使用 CFF Explorer 探索我的 dll 时,我发现 dll 已经具有导出函数的地址,因此理论上我可以链接我的带有 .dll 的程序,无需任何附加文件。

您能否更详细地解释一下 .lib 文件中存储了哪些数据。
而且,是的,我知道,Visual Studio 强制我们将 .lib 文件添加到附加依赖项部分,但为什么它真的需要它们?


当你的源代码静态地调用导出的 DLL 函数,或者静态地访问导出的 DLL 变量,这些引用将作为指针编译到可执行文件的中间对象文件中,其值在运行时填充。

当链接器组合编译器生成的目标文件以生成最终的可执行文件时,它必须弄清楚所有编译器生成的引用实际引用的内容。如果它无法匹配对可执行文件中某些代码段的给定引用,则需要将其与外部 DLL 匹配。因此它需要知道要查看哪些 DLL,以及这些 DLL 如何导出内容。 DLL 可以按名称或序号导出给定的函数/变量,因此链接器需要一种方法将代码引用所使用的标识符映射到 DLL 中的特定条目。EXPORTS具体表.dll文件(特别是在按序数导出内容的情况下)。静态链接.lib文件为链接器提供该映射信息(即FunctionA映射到序号123 in DLL XYZ.dll, FunctionB映射到名称_FunctionB@4 in DLL ABC.dll, etc).

然后链接器可以填充IMPORTS可执行文件的表,其中包含有关适当的信息EXPORTS所需的条目,然后使代码中的 DLL 引用指向正确的IMPORTS条目(如果链接器无法解析编译器生成的对可执行文件中的一段代码或对特定 DLL 导出的引用,它将因“无法解析的外部”错误而中止)。

然后,当您的可执行文件在运行时加载时,操作系统加载器会查看IMPORTS表来知道需要哪些 DLL 导出,因此它可以将适当的 DLL 加载到内存中并更新表中的条目IMPORTS具有基于每个 DLL 的实际内存地址的表EXPORTS表(如果引用的 DLL 加载失败,或者引用的导出失败,操作系统加载程序将中止加载可执行文件)。这样,当您的代码调用 DLL 函数或访问 DLL 变量时,这些访问就会到达正确的位置。

如果你的源代码,事情会非常不同动态地通过显式调用访问 DLL 函数/变量GetProcAddress()在运行时。在这种情况下,静态链接.lib这些访问不需要文件,因为您自己的代码正在处理将 DLL 加载到内存中并定位它想要使用的导出。

然而,还有第三个选项将上述场景混合在一起:您可以编写代码来访问 DLL 函数/变量静态地但使用你的链接器延迟加载功能(如果有的话)。在这种情况下,你仍然需要静态链接.lib您访问的每个延迟加载 DLL 的文件,但链接器填充一个单独的DELAYLOAD可执行文件中的表包含对 DLL 导出的引用,而不是填充IMPORTS桌子。它将编译器生成的 DLL 引用指向编译器 RTL 中的存根,该存根将用以下地址替换引用GetProcAddress()当存根在运行时第一次被访问时,从而避免了操作系统加载器在加载时填充引用的需要。即使 DLL 导出在加载时不存在,这也允许您的可执行文件正常运行,并且如果从未使用过 DLL,甚至可能根本不需要加载 DLL(当然,如果您的可执行文件确实尝试访问 DLL 导出)动态地并且无法加载,您的代码可能会崩溃,但这是一个单独的问题)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么从 .dll 导入函数时需要 .lib 文件? 的相关文章

  • 同步执行异步函数

    我对此主题进行了大量搜索 并且阅读了本网站上有关此主题的大部分帖子 但是我仍然感到困惑 我需要一个直接的答案 这是我的情况 我有一个已建立的 Winform 应用程序 但无法使其全部 异步 我现在被迫使用一个全部编写为异步函数的外部库 在我
  • C 中的复合语句表达式

    下面的代码不起作用 int i void 999 100 添加括号就可以了 为什么 int i void 999 100 还有另一种方法可以完成此类分配 int i void 999 100 是什么让他们与众不同 在这份声明中 int i
  • 如何在 MFC 中调整对话框大小时移动控件?

    我已经在 MFC 中创建了对话框视图 从下图中可以清楚地看到 如滑块控件和编辑框等 当我调整对话框大小时 这些控件不会移动 在此输入图像描述 https i stack imgur com 7OxAK jpg 我想移动控件以适应对话框 但不
  • 使用静态类型代替变量

    当您的项目不使用命名空间时 有什么方法可以告诉编译器使用静态类型而不是变量吗 例如 我有一个名为 User 的类 它具有各种静态和非静态方法 假设调用了其中一个静态方法GetUser 我想称之为User GetUser 方法来自一个方法 该
  • 使用 Selenium for C# 登录 Facebook

    我一直在使用 Selenium C 框架并尝试进行 facebook 登录 但没有任何运气 这是我到目前为止得到的 基于这篇文章 使用 Selenium 测试 Facebook Connect 应用程序 https stackoverflo
  • 基于 MS Bot Framework 中的响应分支对话框/表单

    我们正在尝试使用 MS Bot Framework 但尚未完全弄清楚如何实现此场景 我们有一个 LUIS 对话框 类型 它工作正常并且经过适当的培训 以常见的三明治为例 LUIS 意图寻找的基本内容是用户询问订单状态 如果问题中提供了订单号
  • 将列表(对象)转换为列表(字符串)

    有没有办法转换List of Object to a List of String 在 c 或 vb net 中而不迭代所有项目 幕后迭代很好 我只想要简洁的代码 Update 最好的方法可能就是进行新的选择 myList Select f
  • C 中“for”循环中的两个变量

    我正在编写一些代码 需要在其中使用两个变量for环形 下面的代码看起来没问题吗 它确实给了我预期的结果 for loop 1 offset loop 2 offset 2 loop 1 gt offset 190 loop 2 lt 190
  • 控制器中的异常处理 (ASP.NET MVC)

    当您自己的代码抛出异常并从控制器中的操作调用时 应该如何处理 我看到很多最佳实践的例子 其中根本没有 try catch 语句 例如 从存储库访问数据 public ViewResult Index IList
  • 如何附加到 xml

    我有这个xml
  • 在不使用 Thread.Sleep c# 的情况下延迟发送电子邮件

    我有一个 for 循环 它循环并每个循环发送一封电子邮件 现在我正在使用 thread sleep 但我希望用户仍然能够与程序交互 只需取消该循环即可 是否可以在不使用 thread sleep 的情况下做到这一点 您是否在 UI 线程上运
  • 如何用C++解析复杂的字符串?

    我试图弄清楚如何使用 解析这个字符串sstream 和C 其格式为 string int int 我需要能够将包含 IP 地址的字符串的第一部分分配给 std string 以下是该字符串的示例 std string 127 0 0 1 1
  • .Net Core 中的脚手架以及解决方案中的多个项目

    我创建了一个针对 net461 的 Net Core MVC6 应用程序 我使用了一个我非常熟悉的项目结构 其中我将数据 模型和服务类放置在单独的类库项目中 并且 Web 项目引用这些项目 当我尝试搭建控制器时 我收到一条错误 指出我正在搭
  • 为什么 std::ranges::filter_view 对象必须是非常量才能查询其元素?

    include
  • System.diagnostics.process 进程在托管后无法在 IIS 上运行?

    我正在尝试从网络应用程序安装 exe 当我在本地运行应用程序 从 asp 开发服务器 时 它安装正确 但当我托管在 IIS 上时 它不起作用 我在asp net页面的Page load方法上编写了这段代码 想要在客户端计算机上安装Test
  • 如何解释“错误C2018:未知字符'0x40'?[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 在编译一些代码时 我收到以下信息 错误 C2018 未知字符 0x40 我想知道如何解决这样的问题 这是我要开始的地方
  • C 中什么函数可以替换字符串中的子字符串?

    给定一个 char 字符串 我想查找所有出现的子字符串并将其替换为备用字符串 我没有看到任何简单的函数可以实现这一点
  • double 类型的静态类成员的常量表达式初始值设定项

    在 C 11 和 C 14 中 为什么我需要constexpr在下面的代码片段中 class Foo static constexpr double X 0 75 而这会产生编译器错误 class Foo static const doub
  • 将小数格式化为两位或整数

    对于 10 我想要 10 而不是 10 00 对于 10 11 我想要 10 11 没有代码可以实现吗 即通过指定格式字符串类似于 0 N2 decimal num 10 11M Console WriteLine num ToString
  • 如何将 char 转换为 unsigned int?

    我有一个字符数组 它实际上用作字节数组 而不是用于存储文本 在数组中 有两个特定字节表示我需要存储到无符号 int 值中的数值 下面的代码解释了设置 char bytes bytes 2 bytes 0 0x0C For the sake

随机推荐

  • 如何在 Playwright Python 中获取元素的属性值

    我在一个项目中使用 Playwright Python 我正在努力获得 href 元素的属性值 For Selenium I used el driver find element by xpath a link el get attrib
  • Gradle - 将目录添加到类路径

    我的应用程序要求 config当它在目录下查找配置文件时 目录在类路径上可用 我目前的依赖项配置如下 尽管这可能不是使目录可供我的应用程序使用的正确方法 dependencies runtime compile dependencies p
  • JavaScript 中的布尔对象和布尔数据类型有什么区别?

    布尔类型有两个字面量 值 true 和 false 不要混淆原始布尔值 值 true 和 false 与 true 和布尔值的假值 目的 布尔对象是 原始布尔值的包装 数据类型 有关更多信息 请参阅布尔对象 信息 这是什么意思 布尔对象和布
  • mongodb:获取特定文档然后获取其余文档的最佳方式

    假设我有 1000 个文档 每个文档都有 user id text 现在 我想提取所有这些文档 但首先从一些特定用户 给定用户 ID 数组 中提取文档 然后再提取所有其余文档 我正在考虑如果 user id 存在于特定用户数组中 使用作用域
  • 未找到具有有效签名身份(即证书和私钥对)的配置文件

    是的 我知道这个问题有很多重复 但我尝试了其他人建议的所有内容 此时我没有重复项 我从头开始撤销并重新生成了证书和密钥 我将我的证书与相应的密钥配对 我面临的问题如下 如果我尝试在构建设置中使用发行配置文件进行发布 我会不断收到标头中指定的
  • 如何将 xml 字符串读入 XMLTextReader 类型

    我有一个 XML 字符串 我需要将此字符串转换为XML文本阅读器 System Xml XMLTextReader 输入 dotnet 我使用了以下代码 string szInputXml
  • 如何编辑 JavaScript 警报框标题?

    我正在 C NET 页面中使用以下代码生成 JavaScript 警报 Response Write 它显示一个标题为 来自网页的消息 的警告框 标题可以修改吗 不 你不能 这是一项安全 反网络钓鱼功能
  • Solr:如何搜索多个字段

    我正在使用 solrnet 我有标题和描述字段 我需要同时搜索这两个字段 我该怎么做呢 Jayendra 的答案是正确的 但如果您想在索引时 copyFields 不聚合单个字段中的数据并希望在查询时执行此操作 而不是使用标准处理程序而不是
  • 选项卡行为 Resharper Intellisense 选项

    像 Resharper 这样的产品有很多设置 但我似乎无法找到正确的设置来获得我想要的确切行为 我试图改变的行为是这样的 假设我想要的最终结果是 但目前的线路是 正如你所期望的 我开始输入 一个选项卡后我得到这个 但我希望它成为 有谁知道如
  • 批处理 - 将变量与正则表达式进行比较

    我正在编写一个批处理脚本 必须检查计算机上是否安装了某些程序 为此 我执行programName version我将输出存储在变量中 问题是当我尝试与正则表达式进行比较时 只是为了知道该程序是否存在于机器中 我正在尝试这段代码 但不起作用
  • 使用 Python 在大型文本文件中查找和替换特定行的最快方法

    我有一个numbers txt文件由多个 100K 行组成 每行由两个唯一的数字组成 并用 sign 407597693 1604722326 2426915 510905857 1604722326 2696202 76792361 16
  • 你真的需要“finally”块吗

    java 中的 try catch finally 块有 3 种排列 试着抓 尝试 抓住 终于 尝试 终于 一旦执行了finally 块 控制就会转到finally 块之后的下一行 如果我删除finally块并将其所有语句移至try cat
  • 输入一系列音符并播放它们

    我和我的儿子正在尝试编写一个程序 允许用户输入一系列音符 并将它们保存到要播放的列表中 我们提出了以下方案 import math import needed modules import pyaudio sudo apt get inst
  • node-webkit 相当于 sinatra 吗?

    我一直在考虑学习如何基于 Web 技术制作简单的 Mac OS X 应用程序 并且我遇到了似乎很有吸引力的 node webkit 然而 我最近投入了学习 Sinatra Ruby 的基础知识 并且我想继续学习该课程 对于使用 Sinatr
  • Objective C 协议相当于 Java 接口吗?

    问题不仅仅是关于标题 更多的是 我将如何实现这一目标 而不试图将 Java Flash 设计强制到 Objective C iPhone 程序中 我有 6 个扩展 UIView 的视图 这些视图都有不同的行为 但共享某些方法 例如 void
  • 在相机视图上显示自定义按钮

    有谁知道是否有一种方法可以在相机视图上粘贴自定义按钮 以允许用户像 oink 或 instagram 一样从其库中选择照片 而无需创建自定义视图 谢谢 Edit 使用覆盖层添加按钮似乎很容易 有谁知道如何实际显示照片库并使用该人选择的内容
  • KendoMobile ui 模板不渲染 css 如何使模板在视图中使用 kendo stylng 进行渲染?

    基本上模板不会使用以下方式渲染到 ScrollViewkendo render template response 但会与content template response 但这没有视图中的样式 请参阅下面的评论 如何使模板在视图中呈现剑道
  • Animate.spring 完成后调用函数

    我正在使用动画以便弹出窗口从右侧进入 我为此使用以下代码 var toValue 200 if this state fileMenu toValue 0 Animated spring this state bounceValue toV
  • Cgo 找不到像 这样的标准库

    我试图在我的 Go 代码中包含 C 代码 但未被识别 我首先认为它认为它是 C 代码并尝试 并失败 编译 但删除包含行实际上给了我这样的 C 错误故障排除error cout is not a member of std 该代码可以使用 g
  • 为什么从 .dll 导入函数时需要 .lib 文件?

    你能帮我理解 为什么从 dll 导入函数和数据时需要 lib 文件吗 我听说它包含来自相应 dll 的导出函数和数据元素的列表 但是当我使用 CFF Explorer 探索我的 dll 时 我发现 dll 已经具有导出函数的地址 因此理论上