【问题标题】:Mixing C and C++ libraries混合 C 和 C++ 库
【发布时间】:2014-04-03 01:04:03
【问题描述】:

我在构建一个用 C++ 编码的可执行文件时遇到了一个奇怪的问题,该可执行文件使用了一个 C++ 库,该库本身依赖于一个 C 库。我使用 gcc 编译了构成 C 库的 C 模块,并使用 g++ 编译了所有其他源模块。 C 和 C++ 库都是静态库。

当我在 C++ 源代码中包含来自 C 库的头文件时,我总是将它包装在 extern "C" 中:

extern "C"
{
  #include <c-library-header.h> 
}

现在奇怪的是在链接时出现“未定义的引用”错误,但这些会根据我列出库的顺序而变化:

  • 如果我首先列出 C 库,则该库中 C++ 模块引用的所有符号都显示为“未定义”。
  • 如果我首先列出 C++ 库,则该库中 C++ 模块引用的所有符号都显示为“未定义”。

我原以为静态库出现在 g++ 命令行上的顺序完全无关紧要。谁有线索?

【问题讨论】:

    标签: c++ c gnu


    【解决方案1】:

    顺序很重要。

    如果libxxx依赖于libyyy,则应先指定libxxx,即-lxxx -lyyy

    不幸的是,当两者相互依赖时,一个库可能会被提及两次

    -lxxx -lyyy -lxxx
    

    见:

    【讨论】:

    • +1 以获得很好的答案。不过让我大吃一惊。这一次微软做得很好,因为它的链接器不需要我担心这些愚蠢的细节。
    【解决方案2】:

    而不是多次列出库(如果有许多相互依赖的库,这可能很麻烦),可以依靠 GNU ld 来做正确的事情并来回搜索库列表,直到解决所有符号。这是使用start_group/end_group 命令行开关实现的:

    g++ <...flags...> -Wl,--start-group -lxxx -lyyy -Wl,--end-group <...other flags...>
    

    或者如果它们碰巧以“不合格”的方式命名,则直接提供档案:

    g++ <...flags...> -Wl,--start-group xxx.a yyy.a -Wl,--end-group <...other flags...>
    

    为这样一个简洁的功能付出的代价是降低了链接速度,在许多情况下,这并不重要。

    【讨论】:

    • 只是插话说-Wl, 位很重要,我在gcc 手册页中找到--start-group 后首先尝试使用它,但如果你忘记了-Wl,,它只是默默地跳过它,没有错误消息。无法弄清楚为什么它没有按记录工作。
    • 有谁知道为什么 GNU ld 不默认为多次传递?
    • 因为它在大链接上相当慢,而在小链接上很少需要。
    • 您只需要在第一次通过后仍有未解析的符号时才需要这样做,因此它不会减慢任何没有它的工作。
    • 好吧,你不是第一个想知道这个确切问题的人:stackoverflow.com/questions/16838719/… :)
    猜你喜欢
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多