What Is the Effect of Extern "C" in C++

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

difference between extern C and simply extern [duplicate]

The presence of extern "C" in a C++ file is a personal intent to disable name-mangling transformation that the C++ compiler does to the functions in that file. When there is no name-mangling, then a client C code can call these functions. This is done when you have a mixture of C/C++ code and you need to keep track of language-specific features. In a bit more geeky way, the C linkage becomes compatible in presence of a Cpp compiler.

The code could be anything from a variable/typedef to a full function/module declaration.

But if you do this:

extern char c; // same goes true for extern int foo()

it means that you are saying "I am using char c, which has a declaration external to this file". More like in another module somewhere in the search-path. This is implicitly global. In runtime, if c changes, the change is reflected everywhere. This is provided that your compiler directives such as -Iinclude_file_dirs -Ssource_file_dirs etc. are provided correctly (on GCC or g++). Using a powerful IDE such as Visual Studio 2010 or later, you can do these very easily.

"extern" is a linkage keyword. You can combine it with "C" for compiler-specific linkage directives.

What exactly do I lose when using extern C in C++? [duplicate]

The only thing that gets dropped is name mangling of externally visible names. Function overloading by parameter types, as well as by parameter count, stop working as the result. Essentially, name resolution during the linking phase goes back to the plain old C mode (i.e. one name - one entry).

As far as the internals of your implementation go, you can continue using the standard library and all the other nice features of C++11. Only the names of externally visible entities get changed by extern C.

Why do we need extern C{ #include foo.h } in C++?

C and C++ are superficially similar, but each compiles into a very different set of code. When you include a header file with a C++ compiler, the compiler is expecting C++ code. If, however, it is a C header, then the compiler expects the data contained in the header file to be compiled to a certain format—the C++ 'ABI', or 'Application Binary Interface', so the linker chokes up. This is preferable to passing C++ data to a function expecting C data.

(To get into the really nitty-gritty, C++'s ABI generally 'mangles' the names of their functions/methods, so calling printf() without flagging the prototype as a C function, the C++ will actually generate code calling _Zprintf, plus extra crap at the end.)

So: use extern "C" {...} when including a c header—it's that simple. Otherwise, you'll have a mismatch in compiled code, and the linker will choke. For most headers, however, you won't even need the extern because most system C headers will already account for the fact that they might be included by C++ code and already extern "C" their code.

extern C---when *exactly* to use? [duplicate]

Name mangling rules are different for C. And C can have a different ABI than C++. These reasons alone require you to use extern "C" when embedding C code in C++ code. Even if a compiler can compile both C and C++ code, it might use different name mangling rules or ABIs for the two languages.

Also, your assertion that "[C code is] most likely ... legal c++ code" is not quite true, as C and C++ have diverged more and more as the years have gone on. They have a lot of similarities, but they also have a good number of differences.

When to use extern C in C++? [duplicate]

extern "C" makes names not mangled.

It used when:

  1. We need to use some C library in C++

    extern "C" int foo(int);
  2. We need export some C++ code to C

    extern "C" int foo(int) { something; }
  3. We need an ability to resolve symbol in shared library -- so we need to get rid mangling

    extern "C" int foo(int) { something; }
    ///
    typedef int (*foo_type)(int);
    foo_type f = (foo_type)dlsym(handle,"foo")

Why would you use 'extern C++'?

The language permits:

extern "C" {
#include "foo.h"
}

What if foo.h contains something which requires C++ linkage?

    void f_plain(const char *);
extern "C++" void f_fancy(const std::string &);

That's how you keep the linker happy.

Different linkage for extern C vs. extern C { } in C++ [duplicate]

See here:

[extern "C" { ... }] Applies the language specification string-literal to all function types, function names with external linkage and variables with external linkage declared in declaration-seq.

Since const int my_var1 = 21; has internal linkage, wrapping extern "C" { } around it has no effect.

Also:

[extern "C" ...] Applies the language specification string-literal to a single declaration or definition.

and

A declaration directly contained in a language linkage specification is treated as if it contains the extern specifier for the purpose of determining the linkage of the declared name and whether it is a definition.

extern "C" int x; // a declaration and not a definition
// The above line is equivalent to extern "C" { extern int x; }

extern "C" { int x; } // a declaration and definition

This explains why for extern "C" const int my_var2 = 42; the variable has external linkage and an unmangled name. It also explains why you're seeing an undefined reference to my_var2 in your second code example.



Related Topics



Leave a reply



Submit