【问题标题】:what does __declspec(dllimport) really mean?__declspec(dllimport) 的真正含义是什么?
【发布时间】:2012-02-10 09:38:12
【问题描述】:

我看到的Qt源代码是这样的:

class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};

Q_CORE_EXPORT 宏定义如下:

define Q_DECL_IMPORT __declspec(dllimport)

那么__declspec(dllimport) 的真正含义是什么?

【问题讨论】:

标签: c++ qt visual-c++ dll declspec


【解决方案1】:

__declspec 是 Microsoft 特定的属性,允许您指定存储类信息。
(Nitpicker's Corner:但是,许多其他编译器供应商(例如 GCC)现在支持此语言扩展与针对 Microsoft 编译器编写的已安装代码库的兼容性。有些甚至提供了额外的存储类属​​性。)

可以指定的两个存储类属性是dllimportdllexport。这些向编译器指示函数或对象是从 DLL 中导入或导出的(分别)。

更具体地说,它们定义了客户端的 DLL 接口,而不需要模块定义 (.DEF) 文件。大多数人发现使用这些语言扩展比创建 DEF 文件要容易得多。

出于显而易见的原因,__declspec(dllimport)__declspec(dllexport) 通常是相互配对的。您使用dllexport 将符号标记为从DLL 导出,并使用dllimport 将导出的符号导入另一个文件。

正因为如此,并且由于在编译 DLL 时和在使用 DLL 接口的客户端代码中通常使用相同的头文件,所以定义一个在编译时自动解析为适当属性说明符的宏是一种常见模式-时间。例如:

#if COMPILING_DLL
    #define DLLEXPORT __declspec(dllexport)
#else
    #define DLLEXPORT __declspec(dllimport)
#endif

然后用DLLEXPORT标记所有应该导出的符号。

大概这就是Q_CORE_EXPORT 宏的作用,解析为Q_DECL_IMPORTQ_DECL_EXPORT

【讨论】:

  • @Emilio:据我所知,微软发明了__declspec 符号作为对C++ 语言的扩展。我相信 GCC 现在支持它,但这主要是出于与 Microsoft 编译器的兼容性原因。而且我不明白“特定于MS”与“特定于编译器”有何不同。微软编写了一个 C++ 编译器,很多人都在使用它。它带有 Visual Studio。
  • __declspec()dllimport/dllexport 都不是特定于 Microsoft 编译器的。 __declspec 被一系列不同的供应商编译器用于支持 C++ 语言本身的特定于编译器的扩展。几乎所有支持 Microsoft 平台的 C++ 编译器都支持 dllimport/dllexport 扩展,但它们肯定不是唯一可用的扩展。
  • 微软制作了一个编译器。它被称为“Microsoft C/C++ 优化编译器”,cl.exe。很多人错误地将 Visual Studio 称为编译器,但实际上它是 IDE。我不知道为什么人们会挑剔“特定于微软”的含义。这并不意味着“MS 环境”(无论是什么),当然也不意味着“Windows”。是的,其他编译器供应商现在支持扩展以与针对 Microsoft 编译器编写的已安装代码库兼容。正如我之前所说,据我所知,微软发明了语法。这就是这里的重点。
  • @CodyGray:微软单独发明它是不够的。 然而微软发明了它,没有包含它的标准,其他人只是为了兼容性而实现它,并且它主要(如果不是专门)用于针对 Microsoft Windows 的程序一起使用,因此将其称为“Microsoft具体”
  • 这是一个很棒的答案,尤其是关于“因为在编译 DLL 和客户端代码时通常使用相同的头文件”的部分!使导入/导出内容的各个方面一目了然。
【解决方案2】:

__declspec(dllimport) 是一个存储类说明符,它告诉编译器一个函数、对象或数据类型是在外部 DLL 中定义的。

函数或对象或数据类型从具有相应__declspec(dllexport) 的DLL 导出。

【讨论】:

  • 好的。终于,经过2个小时的阅读,我找到了最满意,最简洁,最准确的陈述。
【解决方案3】:

__declspec(dllexport) 告诉编译器通知链接器这些符号需要放在导出表中(在编译 .dll 时),并将这些符号放在导入库 .lib 中。 在编译与 .dll 链接的程序时,__declspec(dllimport) 告诉编译器生成相对于 rip 的 memory-indirect 调用(链接器将填充解析以指向导入表)而不是未定义函数的通常相对直接指令(由于它不能修改指令,链接器插入 thunk 的相对地址,然后创建 thunk,在其中放置相对于 rip 的内存间接跳转到导入表中的函数指针)。这是代码大小和速度优化。导入库 .lib 告诉链接器哪些符号由 .dll 导出,并用作根据与匹配的外部符号表条目的交集创建导入表的指南,并在.text 段。

https://docs.microsoft.com/en-us/cpp/build/importing-function-calls-using-declspec-dllimport?view=vs-2019 https://docs.microsoft.com/en-us/cpp/build/importing-data-using-declspec-dllimport?view=vs-2019 https://stackoverflow.com/a/4490536/7194773

【讨论】:

    【解决方案4】:

    表示函数的定义在动态库中。 有关详细信息和示例,请参阅the documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-06
      • 2012-03-30
      • 2011-10-10
      • 2012-08-03
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多