【问题标题】:Inline and dlimport/dllexport内联和 dlimport/dllexport
【发布时间】:2012-08-09 06:16:30
【问题描述】:

现在我分析一些不是我写的旧代码。在标头中有很多这样的声明:

SVPDSDKDLLEXPORT inline C3vec mult(C3vec src, D3DXMATRIX &m);

SVPDSDKDLLEXPORT 定义为 _declspec(dllexport),如果在 SVPDSDK 中使用;如 _declspec(dllimport),如果它用于任何使用 SVPDSDK.dll 的项目中。这里的内联对我来说似乎很奇怪,因为标题中没有定义,它在 .cpp 文件中,但是 SVPDSDK 和所有使用各自 DLL 的项目的编译和链接都可以毫无问题地执行。我假设它只是被忽略并且函数被导出,就好像它没有被内联一样。

我发现了这个讨论: C++ : inline functions with dllimport/dllexport?

看起来我应该从所有此类声明中删除“内联”,不要混合内联和导出/导入。但后来我在 MSDN 中找到了这个主题: http://msdn.microsoft.com/en-us/library/xa0d9ste

我不明白其中的某些部分。

您可以使用 dllexport 属性将函数定义为内联函数。在这种情况下,函数总是被实例化和导出,无论程序中的任何模块是否引用该函数。假定该函数是由另一个程序导入的。

首先,“函数总是被实例化”,这是什么意思?我只找到关于 C++ 中模板函数实例化的主题,没有任何其他实例化。它是否仅与模板连接?

其次,“函数总是被导出”。我完全不明白。是否有可能在某些情况下不导出带有 declspec(_dllexport) 的函数?在什么情况下?

现在关于导入:

您还可以将使用 dllimport 属性声明的函数定义为内联函数。在这种情况下,函数可以扩展(根据 /Ob 规范),但永远不会被实例化。特别是,如果采用内联导入函数的地址,则返回驻留在 DLL 中的函数的地址。此行为与获取非内联导入函数的地址相同。

同样,我不明白,在这种情况下,实例化是什么意思。

在编写此问题并从 MSDN 分析主题时,我得出了一个结论,即同时导出/导入和内联的函数仅在其项目本身中内联(在我的情况下为 SVPDSDK)并且是非在所有导入项目中内联。它没有在 MSDN 主题中明显声明。如果我没有在任何使用它的项目中导入它,并且我在它的头文件中没有定义,它将是一个普通的内联函数,所以我会得到一个链接错误。然后在我看来,混合内联和导出/导入是可以接受的,认为它与上面提到的stackoverflow讨论中的答案相矛盾。我说的对吗?
而且我仍然不明白关于内联函数实例化的所有这些话。

对不起,我把一些问题合并在一个主题中,但我不知道如何将它分成不同的问题,因为它们是由同一个问题和相同的材料联合在一起的。但是,如果有人能为我澄清这个问题,我将不胜感激。

【问题讨论】:

  • 当 MS 文档看起来很荒谬时,通常那是因为它很荒谬。他们的技术作家并不总是非常了解主题。我认为 WinMain 作为 Win32 程序的机器代码级入口点的臭名昭著的描述仍然存在,但我最近没有检查。
  • 实例化是指生成的代码就像函数不在线一样。

标签: c++ inline dllimport dllexport


【解决方案1】:

事实上,inline 是优化器的一种提示。编译器仍然可以生成带有主体的真实函数,将参数压入堆栈等。这不会破坏任何逻辑。如果您的“内联”函数有超过 10000 行代码,它肯定会这样做。微软甚至有特殊的__forceinline 关键字。猜猜为什么要引入它。

The function is always instantiated and exported ...

这里的措辞可能并不完美。实例化在这里意味着将生成一个主体和一个入口点。这与模板实例化无关。整段表示__declspecinline更重要。

对于dllimport,他们基本上写道dllimport 阻止在当前二进制模块中生成此内联函数的主体,而内联扩展仍然是可能的。

【讨论】:

  • 现在我想,除了你的话“对于 dllimport,他们基本上写道,指定 dllimport 与不指定它是一样的。”正如我现在所理解的,如果我指定“dllimport”和“inline”,要么扩展函数,要么执行动态链接(由编译器决定)。所以,如果我不指定'dllimport',函数可以被扩展或者只是以正常方式实例化(与DLL和导出函数没有连接)。有区别,不是吗?
  • 您的理解是正确的,我在最后一句中的措辞很糟糕。我更新了我的帖子。
猜你喜欢
  • 2012-11-06
  • 2012-02-11
  • 1970-01-01
  • 2016-02-18
  • 2010-09-08
  • 2018-08-05
  • 2023-01-26
  • 2023-03-28
  • 1970-01-01
相关资源
最近更新 更多