预处理器定义是否已编译到库中?

时间:2010-08-24 07:36:29

标签: c++ c-preprocessor

它们(预处理程序定义)是否已编译为静态/动态库?例如, FBX SDK 需要KFBX_DLLINFO。使用 FBX SDK 的库必须包含该库。现在客户端应用程序,从我有限的实验中可以看出,不需要再次声明定义。

现在我想不出更实际的情况,但是如果客户端应用程序“需要”排除的定义(例如用库编译的_CRT_SECURE_NO_WARNINGS,如果我需要那些警告怎么办?< / p>

3 个答案:

答案 0 :(得分:16)

简而言之:不。

长期: 在大多数情况下,您可以将预处理器定义视为文本替换机制。它们在编译发生之前被处理( pre -compilation),因此它们在编译器将其转换为机器代码,中间文件或其目标之前转换源代码。当你有一个二进制lib / obj / dll / exe / so文件时,预处理器定义早已不复存在。

如果在代码中包含一个标题作为库的一部分打包(例如,为了引用库定义的方法,类型,枚举等),那么您将包含库定义的预处理器定义那个标题。

在您的情况下,如果您包含FBX标头,您可能还会引入KFBX_DLLINFO的预处理器定义。您链接的FBX二进制库几乎肯定是使用相同的标头构建的,因此您构建的是相同的定义。这是使用C / C ++编写的库的常见模式:常见的共享头文件以及要构建的静态或动态库。

答案 1 :(得分:2)

预编译器定义仅在编译期间存在。它们在编译的二进制文件中不再存在,无论是静态库还是动态库,还是可执行文件。

答案 2 :(得分:2)

正如克里斯所解释的那样,#define是一种文本替代机制。传统上,扩展是作为预编译步骤执行的,主要的C ++语言编译器没有(或想要)访问预替换文本。因此,#define可以执行C ++基于语言的约束无法实现的功能,例如连接值以形成新的标识符。目前,编译器倾向于嵌入宏处理功能,并且可以在编译成可执行文件的调试符号表中包括关于预处理器符号的一些信息。对于某些客户端使用来说,访问此调试信息并不是非常理想或实际,因为调试格式和内容可能在编译器版本之间发生变化,不是非常便携,调试可能不是很好: - /,并且访问它们可能很慢并且笨拙。

如果我理解正确,您会想知道您的库正在使用的某个较低级别库中的#defines是否会自动可供使用您的库的“应用程序”程序员使用。不,他们不会。您需要为库API向应用程序员公开的那些值提供您自己的定义(如果它们不同,则在内部映射到较低级别的库值),或者也可以提供较低级别的库标题。

有关重新映射的示例:

你的library.h:

#ifndef INCLUDED_MY_LIBRARY_H
#define INCLUDED_MY_LIBRARY_H

enum Time_Out
{
    Sensible,
    None
};

void do_stuff(Time_Out time_out);

#endif

你的library.c:

#include "my_library.h"
#include "lower_level_library.h"

void do_stuff(Time_Out time_out)
{
    Lower_Level_Lib::do_stuff(time_out == Sensible ? Lower_Level_Lib::Short_Timeout,
                                                   : Lower_Level_Lib::No_Timeout);
    LOWER_LEVEL_LIB_MACRO("whatever");
}

如图所示,在my_library.h中没有公开Lower_Level_Lib的使用,因此app程序员不需要知道或包含lower_level_library.h。如果您发现需要/想要将lower_level_library.h放入my_library.h以便在其中使用其类型,常量,变量或函数,那么您还需要为app程序员提供该库头。