具有相同头文件名称的库包含路径

17
什么是把另一个文件夹中与当前文件同名的文件包含进来的最佳方法,而该文件夹是通过附加的include目录访问的?
示例:
lib1/include/foo.h
lib2/include/foo.h

在附加包含目录中添加了lib1/include和lib2/include两个目录。

编辑:

这些库来自不同的SDK,每个开发人员都会将它们安装在自己的位置。唯一确定的是这两个文件夹都在IDE的附加包含路径中。

方法1:

#include "../../lib1/include/foo.h

方法2:

在搜索路径中先添加lib1/include,然后再添加lib2/include,因为按顺序搜索:

#include "foo.h"

将包括lib1/include/foo.h。


1
方法2不好,因为程序编译依赖于代码本身没有的设置(包括目录顺序)。如果有人需要重建项目设置,很难发现这个问题,更不用说正确的设置是什么了。 - Mike DeSimone
@Mike 我知道这些不是最好的方法,但现在这些是我所能想到的唯一方法。因为我不喜欢任何一个方法,所以我在这里寻求更好的方法。 - Mircea Ispas
5个回答

8
#include "lib1/include/foo.h"
#include "lib2/include/foo.h"

只要这是指向那些头文件的实际相对路径,并且包含保护不同,那就可以了。例如,如果两个foo.h使用
#ifndef _foo_h_

如果这样做,会产生您不想要的结果(它只包含其中一个,而不是两个,而且取决于执行顺序)。

非常感谢您,先生。你说得对,关于搜索路径的问题! - Bernd Elkemann

5
您只需要这样做:
#include "lib1/include/foo.h"
#include "lib2/include/foo.h"

请确保lib1lib2的父目录都在您的包含搜索路径中(但不包括实际的include子目录本身)。

请注意,如果两个头文件使用相同的符号作为包含保护,则此方法将无法正常工作-您需要在两个包含之间取消定义冲突的符号:

#include "lib1/include/foo.h"
#undef FOO_H
#include "lib2/include/foo.h"

@Felics:这就是为什么你必须避免使用#include "foo.h"。你是说SDK安装的目录名称(例如此示例中的lib1lib2)不确定吗?如果是这样,你唯一的解决方案就是创建具有不同名称的链接到两个头文件,并使用这些链接来访问头文件。即使如此,由于eznme提到的包含保护问题,这也可能无法正常工作。 - Mike DeSimone
答案是错误的。如果头文件保护相同(很可能是这样),预处理器将不会包含来自lib2的代码。 - Hi-Angel
@Hi-Angel: 谢谢您指出这个问题 - 所有其他答案都提到了这个问题,所以我想我应该在我的答案中包括相同的 警告. - Paul R
最好不要提及它 - 现在我的回答没有意义 ☹ - Hi-Angel
1
总是有几个有用的答案是很好的,即使建议中有一些重叠。无论如何,我会给你的答案点赞。 - Paul R
显示剩余3条评论

5

首先,这个答案假设两个头文件的包含保护是兼容的(即不是相同的符号)。

你可以在已知位置创建指向所需头文件的链接,并为链接本身命名。例如,假设你的两个库被安装在 $LIB1PATH 和 $LIB2PATH,这些值在不同的构建环境中可能有不同的值。因此,你想要获取的头文件位于 $LIB1PATH/include/foo.h 和 $LIB2PATH/include/foo.h。

你可以采取两种方式。一种是创建直接链接。在项目目录树中,这可能看起来像这样:

$PROJDIR/
    include/
    lib_include/
        lib1_foo.h -> $LIB1PATH/include/foo.h
        lib2_foo.h -> $LIB2PATH/include/foo.h
    src/

如果您的代码在存储库中,这可能会变得复杂,因为您无法检查这些链接;它们在其他环境中是错误的。此外,如果您有很多这些链接和很少的库,每当lib1或lib2移动时,您就必须重新创建所有这些链接...这不好。您可以通过在包含项目目录的目录中创建链接来解决此问题:
$PROJDIR/
    include/
    lib_include/
        lib1_foo.h -> ../../lib1/include/foo.h
        lib2_foo.h -> ../../lib2/include/foo.h
    src/
lib1 -> $LIB1PATH/
lib2 -> $LIB2PATH/

在这两种情况下,您需要确保$PROJDIR/lib_include在您的包含路径中。如果这两个foo.h头文件从这些目录中引入了更多头文件,则只需要将$LIB1PATH/include$LIB2PATH/include放入您的包含路径中。您也可以将链接放在“include”中并删除“lib_include”,但我喜欢将这些内容分开。


4

我想知道目前有4个回答和1709个浏览量,为什么还没有人提供如此简单明了的解决方案。

您可以按照自己的需求包含文件,唯一真正的问题在于相同的守卫头文件。因此,您需要创建一个头文件,其中将包含冲突的两个头文件。我们称其为 inc_foo_lib1_lib2.h。在这个文件中,首先包含第一个 foo.h,然后如果已定义守卫头文件,请取消定义,接下来包含第二个 foo.h

例如,假设 foo.h 有一个头文件守卫 FOO_H_INCLUDED,那么您的 inc_foo_lib1_lib2.h 如下所示:

#include "lib1/foo.h"
#ifdef FOO_H_INCLUDED
#undef FOO_H_INCLUDED
#else
COMPILATION ERROR — the header guard was changed!
#endif //FOO_H_INCLUDED
#include "lib2/foo.h"

2

我会从一个明确的目录中包含文件,这个目录在-I列表中(也就是包含lib1和lib2的目录路径):

#include "lib1/include/foo.h"
#include "lib2/include/foo.h"

因此,不会存在任何歧义,因为预编译器将在其目录列表中查看lib1/include/foo.h,而这个操作并不是从lib1/include/lib2/include/进行的,而是从父目录进行的。
正如之前所说:要注意保护宏的使用,即使用于库头文件,名称也应包含库名称以避免出现这种混淆。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接