处理 IDL 文件中的#defines

本页介绍使用 #define 定义的符号为何会从 MIDL 编译器生成的 H 文件中消失,以及可对此执行的操作。 此解释适用于由 MIDL 处理的任何文件,例如 *.idl、*.acf、*.h 文件。

#define符号消失是 MIDL 将输入文件的预处理委托给预处理器的结果。 默认情况下,预处理器是生成环境中的 C/C++ 预处理器。 预处理后,输入流 MIDL 接收只有#line预处理器指令。 具体而言,预处理器会展开输入文件中的所有宏定义,因此 MIDL 无法检测到它们的存在。 因此,当 MIDL 将类型定义从输入文件复制到生成的 H 文件时,不会复制#defines。 因此,如果以后要从生成的 H 文件中使用#defines,请不要直接在 IDL 文件中使用这些文件。

建议使用以下四种解决方法:

  • 使用 const 声明规范。
  • 使用导入或包含在 IDL 文件中的单独头文件,然后包含在 C 源代码中。
  • 在 IDL 文件中使用枚举常量。
  • 使用 cpp_quote 在生成的头文件中重现 #define

可以使用 IDL 常量声明语法重现清单常量。 请注意,IDL 常量声明中的 const 不同于 C/C++ const 语义,它只是为 IDL 编译引入了命名常量。 例如:

const short ARRSIZE = 10

此示例指定 ARRSIZE 是值为 10 的常量。 命名常量可用于 IDL 数组声明符和 C 程序员将使用清单定义的其他位置。 此外,此语法会导致在头文件中生成以下行:

#define ARRSIZE 10

处理 **#**define 语句的另一种方法是将它们打包在单独的头文件中,将其打包到专用于 **#**define 语句的文件中,或打包到仅包含类型定义的文件中。 IDL 文件和 C 源文件可以安全地包含仅包含预处理器指令的文件。 尽管 指令在 MIDL 编译器生成的头文件中不可用,但 C 源程序可以包含单独的头文件。 以类似的方式,可以从 IDL 文件导入包含 **#**define 语句和常规类型定义的头文件。 此方法封装 **#**define 和 typedef 语句,方法是在 H 文件中使用这些语句,以便不直接在导入 IDL 文件中使用 **#**define 符号。 将标头或 IDL 文件导入另一个 IDL 文件可防止 typedef 语句复制到 MIDL (生成的 H 文件,这与 **#**include 语句) 相反。 此方法允许通过生成的 H 文件从 C 代码安全地引用原始头文件,而不会遇到重复定义的问题。

在 IDL 文件中使用枚举常量也是有效的。 这些常量可用于 IDL 中的常量表达式,例如在数组声明符中。 C 编译器预处理器不会在 MIDL 编译的早期阶段删除枚举常量,因此,在 MIDL 编译器生成的头文件中提供了枚举常量。 请考虑下列语句:

typedef enum midlworkaround { MAXSTRINGCOUNT = 300 };

C 预处理器在 MIDL 编译期间不会删除此语句,typedef 将复制到生成的 H 文件。 常量 MAXSTRINGCOUNT 可用于包含 MIDL 编译器生成的头文件的 C 源程序。

最后,可以使用 MIDL 的 cpp_quote 指令将任意字符串直接写出到生成的 H 文件中。 例如,若要获取以前在此页上使用 cpp_quote 的清单常量,可以使用以下语句:

cpp_quote ("#define ARRSIZE 10")

此语句导致在头文件中生成以下行:

#define ARRSIZE 10