c ++库命名空间和C linux函数之间的名称冲突

时间:2016-05-23 14:14:18

标签: c++ linux namespaces name-collision

Linux <ncurses.h>标头定义函数meta,C ++元编程库meta将其所有代码放在全局名称空间meta中。

如何在同一个C ++程序中使用它们(不一定是相同的TU,但这样会很好)?有没有办法解决名称冲突?

我可以想到两个脆弱的解决方法,但它们很容易破解:

  • 解决方法A:

     namespace linux {
     #include <ncurses.h>
     }  // namespace linux
     using linux::max_align_t;  // ncurses assumes it is in the global namespace
     #include <meta/meta.hpp>
    

    编译但可能无法链接,因为全局命名空间中需要ncurses个符号。

  • 解决方法B:

    #include <ncurses.h>
    namespace cpp {
    #include <meta/meta.hpp>
    }  // namespace cpp
    

    非常脆弱,因为只有meta库没有假设它的任何符号都在全局命名空间中时它才会起作用。也就是说,如果库需要在内部消除符号歧义并使用::meta::symbol_name,那么这种方法就会中断。

2 个答案:

答案 0 :(得分:7)

我建议解决方法C:隔离代码,使meta库使用和ncurses使用在项目的单独翻译单元中。这种方式在任何特定的翻译单元中都没有一个符号被用作命名空间和全局函数。

答案 1 :(得分:1)

我合理地确定A和B都不会真正起作用,至少是给定的。你已经指出了其中一个,但我认为这两者的可能性较小。有两个问题基本上是彼此的镜像。

如果extern "C"中的代码被声明为extern "C"(对于许多使用C ++的C库来说是典型的),用命名空间包围它们实际上不会起作用 - <ncurses.h>声明基本上忽略了名称空间并在全局名称空间中声明了一个函数。命名空间不会发生任何变化,你仍然会发生冲突。

如果extern "C"的内容未声明为linux,那么您将遇到您引用的问题:库是使用全局命名空间中的函数构建的,但客户端代码是查看linux::*命名空间中代码的定义。由于命名空间会影响损坏的名称(它是如何防止冲突),因此您的代码无法链接。所有extern "C"函数都将显示为未解析的外部。

为了完成这项工作,您需要确保没有任何库代码被声明为:([^|]+)(?:\||$) ,并在头部(和库源文件)中指定 中的命名空间 - 使用这些声明编译库,因此库及其客户端代码就该代码所在的命名空间达成一致。