C++ 命名空间内的 extern "C" 链接?

extern "C" linkage inside C++ namespace?

namespace someNameSpace {
    extern "C" void doSomething()
        {
             someOperations();
        }
}

我想在 C++ 和 C 环境中 运行 doSomething()

如果我将它暴露给 extern "C" 链接,someNameSpace 是否仍在封装 doSomething()

有没有一种在 C++ 和 C 之间共享函数同时避免在 C++ 端污染全局命名空间的好方法?

编辑:因为这段代码主要用于C++模式,而C链接只是为了测试使用,我想这是一个更好的方法。

namespace someNameSpace {
    #ifdef COMPILE_FOR_C_LINKAGE
    extern "C"
    #else
    extern "C++"
    #endif
    { 
        void doSomething()
            {
                 someOperations();
            }
    }
}

您的代码有效,但您应该注意所有具有 extern "C" 链接的函数共享相同的 space 名称,但不要将其与 [=21] 的 C++ 概念混淆=]:您的函数确实是 someNameSpace::doSomething,但您不能在任何其他名称 space.

中使用任何其他 extern "C" 具有不合格名称 doSomething 的函数

见 7.5/6:

At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. Two declarations for a variable with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same variable. An entity with C language linkage shall not be declared with the same name as a variable in global scope, unless both declarations denote the same entity; no diagnostic is required if the declarations appear in different translation units. A variable with C language linkage shall not be declared with the same name as a function with C language linkage (ignoring the namespace names that qualify the respective names); no diagnostic is required if the declarations appear in different translation units. [Note: Only one definition for an entity with a given name with C language linkage may appear in the program (see 3.2); this implies that such an entity must not be defined in more than one namespace scope. — end note]

您公司或项目的全局风格仲裁者应该能够为您的代码库提供合适的命名策略建议。

只是一段代码来说明 Kerrek SB 回答中所述的行为

#include <iostream>

namespace C{
    void Hello(){
        std::cout<<"Hello"<<std::endl;
    }
    extern "C" void HelloThere(){
        std::cout<<"Hello There from extern \"C\""<<std::endl;
    }
}

extern "C" void HelloThere();

int main() {
    C::Hello();
    C::HelloThere(); //Compiles
    //Hello(); <--- does not compile
    HelloThere(); //Also compiles and prints the same as C::HelloThere() !!!

    return 0;
}

住在http://ideone.com/X26wfR

在 C++ ABI 中,名称空间必须被破坏。所以这个:

namespace foo
{
    void bar(int){}
}

大致翻译成这样的符号:

foo::bar(int)

强制编译器使用C ABI时,类似的符号

namespace foo
{
    extern "C" void bazz(int){}
}

编译后如下所示:

bazz

你可以看出神螺栓的区别: https://godbolt.org/z/BmVpSQ

在 C ABI 中,函数没有命名空间或参数列表,因此整个代码中只能有 1 个这样的符号。定义两次:

namespace foo
{
    extern "C" void bazz(int){}
}

namespace foo2
{
    extern "C" void bazz(int){}
}

int main()
{
    foo2::bazz(5);
    return 0;
}

...是非法的。在这种情况下,clang 编译器只会发出简单的编译错误:

https://wandbox.org/permlink/r5CUXm7OKePtG35L

gcc 编译器也报错,但看起来更神秘:

https://wandbox.org/permlink/BiN0auna9klBg5GE