【问题标题】:Check a __declspec macro in preprocessor检查预处理器中的 __declspec 宏
【发布时间】:2018-01-19 22:04:43
【问题描述】:

如果我有SOME_MACRO 定义为__declspec(dllimport)__declspec(dllexport),有没有办法在编译时检查正在使用哪个?

即像这样:

#if SOME_MACRO == __declspec(dllimport)
// do something
#else
// do something else
#endif

UPD。 看看我得到的答案,我想我应该更具体地说明我为什么需要这个。

我正在尝试编译一个相当大的第 3 方库,该库在包含它的大部分代码中都有一个声明为 dllexport 的函数。然而,有一个组件是dllimport

我需要稍微修改 dllimport 案例的声明。两个声明之间的切换不是很简单,它是一个相当深的#ifdef 指令树分布在多个文件中的结果。原则上我可以从这些说明中挖掘出这些信息,但为了确保我做得正确,我必须尝试在几种不同的配置下编译整个库(每次编译需要几个小时)。

另一方面,如果有一种简单的方法可以检查他们的 SOME_MACRO 是否被评估为导入或导出,我可以在一个小程序上进行测试,快速安全地将其放入库中。

【问题讨论】:

  • __declspec 不是宏,它是 Visual C++(和兼容的)编译器中的特殊关键字。
  • 使用确定 SOME_MACRO 值的相同逻辑?
  • @Someprogrammerdude 感谢您的评论,很抱歉混淆了条款。不过,我想我想要检查的内容应该很清楚。
  • @AnonMail 原则上,这是一个选项。但是这个逻辑是由其他人实现的,有点复杂,所以我希望有一种简单的方法可以在编译时检查它。

标签: c++ c-preprocessor


【解决方案1】:

你不能使用

#if SOME_MACRO == __declspec(dllimport)

__declspec(dllimport) 不是预处理器表达式的有效标记。

您最好的选择是使用另一个预处理器宏,例如:

// Are we building the DLL?
#if defined(BUILD_DLL)
   // Yes, we are.
   #define SOME_MACRO __declspec(dllexport)
#else
   // No. We are using the DLL
   #define SOME_MACRO __declspec(dllimport)
#endif

现在,您可以使用:

#if defined(BUILD_DLL)

根据您是构建 DLL 还是使用 DLL 来包含条件代码。


实际上,这最终会涉及更多一点。

  1. 大多数项目都有不止一个 DLL。 BUILD_DLL 不行。您构建的每个 DLL 都需要 BUILD_xxx_DLL。假设您有两个 DLL,实用程序和核心。以及依赖于两者的应用程序。

  2. 您可能还需要创建一个静态库。

在实用程序库的每个公共 .h 文件中,您都需要类似以下内容。

#if defined(BUILD_UTILITY_STATIC)
   #define UTLIITY_EXPORT
#elif defined(BUILD_UTILITY_DLL)
   #define UTLIITY_EXPORT__declspec(dllexport)
#else
   #define UTLIITY_EXPORT__declspec(dllimport)
#endif

当然,您不希望在大量 .h 文件中重复相同的代码。您将创建一个包含上述内容的 .h 文件和所有其他 .h 文件中的 #include

在构建utility.dll 时,您需要定义BUILD_UTILITY_DLL 并保留BUILD_UTILITY_STATIC 未定义。

在构建 utllity.lib(静态库)时,您需要定义 BUILD_UTILITY_STATIC 并保留 BUILD_UTILITY_DLL 未定义。

utility.dll 的用户将留下 BUILD_UTILITY_STATICBUILD_UTILITY_DLL 未定义。

utility.lib(静态库)的用户需要定义 BUILD_UTILITY_STATIC 并保留 BUILD_UTILITY_DLL 未定义。

对于 core.dll 和 core.lib,您需要一个类似的文件。

【讨论】:

  • 感谢您的建议。在我的例子中,这个BUILD_DLL 逻辑是由其他人实现的。而且它有点太复杂了,所以我希望也许我可以将SOME_MACRO 字符串化然后检查,或者其他什么...
  • @SiLiKhon,这听起来很有希望。您可以挖掘一下并找出BUILD_DLL 的等价物。您可以使用该宏来包含您的条件代码。
【解决方案2】:

宏由 DLL 创建者命名。

  • 您需要在导出或导入模式下工作的头文件。
  • 将使用 C/C++ 文件来创建程序、构建 DLL(导出)。
  • 其他 C/C++ 文件将用于调用 DLL(导入函数)。

在构建实现​​文件中,您命名的宏在包含标头之前定义。 例如

#define DLLNAME_BUILD_DLL
#include "dll_header.h"

在标题中,如果定义了宏,则模式设置为导出。使用 DLL 时不定义宏,而是导入函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2015-07-31
    相关资源
    最近更新 更多