When to use extern "C"?

916 views Asked by At

I know how to use extern "C" but what are the conditions when you have to use it?

extern "C" tells the C++ compiler not to perform any name-mangling on the code within the braces. This allows you to call C functions from within C++.

For example:

#include <string.h>

int main()
{
    char s[] = "Hello";
    char d[6];

    strcpy_s(d, s);
}

While this compiles fine on VC++. But sometimes this is written as:

extern "C" {   
#include <string.h>  
}

I don't see the point. Can you give a real example where extern "C" is necessary?

6

There are 6 answers

0
morechilli On

If you are producing a binary library A that exposes a function that you would like to call from binary B.

Imagine A is A.dll and B is B.exe and you are on a Windows system.

C++ does not describe a binary layout such that B knows how to call A. Typically this problem is worked around by using the same compiler to produce A and B. If you want a more generic solution you use the extern keyword. This exposes the function in a C manner. C does describe a binary format so that different binaries from different compilers can talk to each other.

See: http://en.wikipedia.org/wiki/Application_binary_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

0
Basile Starynkevitch On

If, inside your C++ code, you #include a header for an external library (coded in C) and if the functions there are not declared extern "C" they wont work (you'll get undefined reference at link time).

But these days, people coding C libraries and providing header files for you tend to know that, and often put the extern "C" in their header file (suitably protected with #ifdef __cplusplus)

Perhaps a better way to understand is to use (assuming you have a Linux system) the nm utility to show you the (unmangled) names used in a library or an executable.

0
NPE On

Here is a concrete example of where things break and need extern "C" to get fixed.

module.h:

int f(int arg);

module.c:

int f(int arg) {
  return arg + 1;
}

main.cpp:

#include "module.h"

int main() {
  f(42);
}

Since I am mixing C and C++, this won't link (of the two object files, only one will know f under its C++ mangled name).

Perhaps the cleanest way to fix this is by making the header file compatible with both C and C++:

module.h:

#ifdef __cplusplus
  extern "C" {
#endif

int f(int arg);

#ifdef __cplusplus
  }
#endif
0
David Heffernan On

One very common use of extern "C" when you are exporting a function from a library. If you don't disable C++ name mangling you can otherwise make it very hard for clients of your library to name your function. And likewise, when going in the other direction, when you are importing a function that has been exported with C linkage.

2
paxdiablo On

You use extern "C" to prevent name mangling inside header files and your C++ object files for libraries or objects that have already been compiled without mangling.

For example, say you have a widget library which was compiled with a C compiler so that its published interface is non-mangled.

If you include the header file as is into your code, it will assume the names are mangled and those mangled versions are what you'll tell the linker to look for.

However, since you'll be asking for something like function@intarray_float_charptr and the widget library will have only published function, you're going to run into problems.

However, if you include it with:

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

your compiler will know that it should try to use function, the non-mangled version.

That's why, in header files for C stuff meant to be included in C _or C++ programs, you'll see things like:

#ifdef __cplusplus
    extern "C" {
#endif

// Everything here works for both C and C++ compilers.

#ifdef __cplusplus
    }
#endif

If you use a C compiler to include this, the #ifdef lines will cause the extern "C" stuff to disappear. For a C++ compiler (where __cplusplus is defined), everything will be non-mangled.

0
AndersK On

When you link with libraries that are written in C extern tells the compiler not to decorate the names so that the linker can find the functions. In C++ function names et al have information for the linker e.g. argument types and sizes contained in the name.