extern "C" linkage inside C++ namespace?

In C++ ABI, namespaces have to be mangled. So this:

namespace foo
{
    void bar(int){}
}

is translated more or less to such symbol:

foo::bar(int)

When you force the compiler to use C ABI, the similar symbol

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

after compilation looks like following:

bazz

You can see the difference in the godbolt: https://godbolt.org/z/BmVpSQ

In C ABI there are no namespaces or argument list mangled with the function, so you can only have 1 such symbol in the whole code. Defining it twice:

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

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

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

...is illegal. The clang compiler just emits simple compilation error in such case:

https://wandbox.org/permlink/r5CUXm7OKePtG35L

The gcc compiler emits error too, but it looks way more misterious:

https://wandbox.org/permlink/BiN0auna9klBg5GE


Your code works, but you should beware that all functions that have extern "C" linkage share the same space of names, but that is not to be confused with the C++ notion of "namespace": Your function is really someNameSpace::doSomething, but you cannot have any other extern "C" function with unqualified name doSomething in any other namespace.

See 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]

Your company's or project's global style arbiters should be able to advise you on a suitable naming policy for your code base.


Just piece of code to illustrate behavior stated in Kerrek SB answer

#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;
}

Live at http://ideone.com/X26wfR

Tags:

C++

C

Namespaces