Extern "C" Linkage Inside C++ Namespace

extern C linkage inside C++ namespace?

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.

extern C inside namespace

You can not inject everything into a namespace under a header. In this case, read is a macro and it is evaluated to something else before namespace resolution rules take effect.

How to declare an extern C function inside a function in C++?

From the C++11 standard (in [dcl.link], emphasis mine):

4 Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope.

(linkage-specification refers to extern string-literal ..., i.e. extern "C" in your case.)

This means you can't have extern "C" inside of a class or function.

What's the point of declaring SomeOtherFunction inside of SomeFunction? It still has to be a global symbol and visible to the linker.

So why not do this?

#ifdef __cplusplus
extern "C"
#endif
void SomeOtherFunction();

inline void SomeFunction() {
SomeOtherFunction();
}

The following also seems to work:

extern "C" {
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
}

But it would have the side effect of making SomeFunction also use C linkage (which is hopefully OK as (per your requirements) it needs to be usable from C, too).

Can I extern the entire namespace?

You seem to be asking two questions. One regarding external linkage and one regarding the extern specifier.


Regarding the linkage, there is not really a need for such a syntax.

External linkage is already the default at namespace scope, whether in the global namespace or another namespace, except for const non-template non-inline variables and members of anonymous unions. (https://en.cppreference.com/w/cpp/language/storage_duration#internal_linkage)

So the other way around, syntax to make all names in a namespace have internal linkage, is more likely to be required and this is possible with unnamed namespaces

namespace {
//...
}

in which all declared names have internal linkage.


Regarding the extern specifier used to turn a variable definition into just a declaration at namespace scope or to give it external linkage explicitly, I am not aware of any syntax to apply it to a whole namespace. You will have to specify it explicitly on each variable.

What is the effect of extern C in C++?

extern "C" makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client C linker will then link to using the C name.

Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C" linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.

Just so you know, you can specify extern "C" linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:

extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}

If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on extern "C"):

  • extern "C" is a linkage-specification
  • Every compiler is required to provide "C" linkage
  • A linkage specification shall occur only in namespace scope
  • All function types, function names and variable names have a language linkage See Richard's Comment: Only function names and variable names with external linkage have a language linkage
  • Two function types with distinct language linkages are distinct types even if otherwise identical
  • Linkage specs nest, inner one determines the final linkage
  • extern "C" is ignored for class members
  • At most one function with a particular name can have "C" linkage (regardless of namespace)
  • extern "C" forces a function to have external linkage (cannot make it static) See Richard's comment: static inside extern "C" is valid; an entity so declared has internal linkage, and so does not have a language linkage
  • Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved

External linkage for name inside unnamed namespace

How to explicitly make external linkage for name inside unnamed namespace

The only way I can think of is to give it C language linkage, so that its linkage name ignores the namespace qualification:

namespace {
extern void f() { } // has internal linkage despite 'extern'
extern "C" void g() { } // ignores linkage of namespace
}
void (*p)() = f; // ensure 'f' won't be optimized away

(A strict reading of the standard suggests that g should have internal linkage, but that's not what compilers seem to do.)

and how to check that linkage is actually external if Standard guaranteed that there is no way to access name defined inside unnamed namespace from another translation unit?

Typically ELF compilers will implement internal linkage with non-global symbols, so you can compile the code and inspect the object file:

$ g++ -c linkage.cc
$ nm linkage.o
0000000000000000 t _ZN12_GLOBAL__N_11fEv
0000000000000007 T g
0000000000000000 D p

The mangled name of the unnamed namespace can vary between compilers, but demangling it will show:

$ nm -C  linkage.o
0000000000000008 t (anonymous namespace)::f()
0000000000000000 T g
0000000000000000 D p

The lowercase t shows that f has local visibility, meaning it can't be linked to from other object files. The uppercase T shows that g has external linkage.

This isn't guaranteed by the standard though, as ELF visibility is not part of the C++ standard, and some compilers implement linkage without using visibility even on ELF platforms, e.g. the EDG compiler produces a global symbol for the same code:

$ nm linkage.o
0000000000000008 T _ZN23_GLOBAL__N__7_link_cc_p1fEv
0000000000000004 C __EDGCPFE__4_9
0000000000000000 T g
0000000000000000 D p
$ nm -C linkage.o
0000000000000008 T (anonymous namespace)::f()
0000000000000004 C __EDGCPFE__4_9
0000000000000000 T g
0000000000000000 D p

So using extern "C" allows you to give a name external linkage even if it appears in an unnamed namespace, but that doesn't make the note correct, because you can refer to that name from other translation units, because it doesn't use the unnamed namespace scope. That suggests to me that the note is simply a leftover from C++03 when entities in unnamed namespaces didn't automatically have internal linkage, and the note should be corrected or removed (and indeed T.C. points out it was already removed by DR 1603).

In which cases doing explicit external linkage for name inside unnamed namespace is useful?

I can't think of any cases where it's useful.

Whether g++ declares a name of C Standard Library as extern C linkage or extern C++?

That would depend on the standard library you are using, not the compiler.

Typically, with g++ you will be using libstdc++, i.e. the GNU C++ Library (which in turn relies on glibc, i.e. the GNU C Library). This one, by default, looks like it uses C linkage for the C names. If you look into the sources themselves, you will currently see 4 different sets of C headers that may be used.

In any case, you shouldn't be relying on that, and it also may change with no warning, even between releases.

Ideally, if you need the exported name for some reason (whether mangled or not), you should directly pick it up from the shared object or from the headers your compiler is using, instead of relying on a given linkage.

Having said that, the major standard libraries/compilers provide them as extern "C", even MSVC on Windows; and even if you use the C++ cname headers (the ones in the global namespace, of course).



Related Topics



Leave a reply



Submit