5

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user103214
  • 3,478
  • 6
  • 26
  • 37
  • 7
    Instead of hacking `` to avoid name mangling, use the `` header. – Alexandre C. Nov 03 '11 at 14:02
  • @AlexandreC.: it's absolutely not a good idea to use the `` headers. A `` header is *not* guaranteed to place identifiers in the global namespace, thus breaking code that relies on global namespace identifiers when that code is moved to some other compiler. Also, a `` header may and in practice will place identifiers in the global namespace, thus in theory also breaking code that relies on a non-polluted global namespace. "In theory" is too vague though; at least one idiot did that. So, don't use them. – Cheers and hth. - Alf Nov 03 '11 at 14:35
  • @AlfP.Steinbach: If you write C++, use ``. If you write C, use `` and **compile your code with a C compiler**. Mixing languages is *not* a good idea. – Alexandre C. Nov 03 '11 at 15:18
  • @user974191: I've never had to wrap a standard C library `#include` inside an `extern "C"`. Standard C library headers take care of checking if `__cplusplus` is defined and adding `extern "C"` for you. Where you might have to wrap in `#include` inside `extern "C"` would be a 3rd-party C library that didn't do the `#ifdef __cplusplus` checking for you. – Emile Cormier Nov 03 '11 at 15:27
  • 1
    @AlexandreC.: your advice is all association and no reasoning. it's dumb. – Cheers and hth. - Alf Nov 03 '11 at 15:32
  • 1
    @AlfP.Steinbach: What if you prefix `std::` in front of every function you call from a `` header? Can there still be portability problems? – Emile Cormier Nov 03 '11 at 16:45
  • @Emilie: Yes. Because that's a *convention*. And conventions are not checked by the compiler. A convention is especially likely to be broken when there is a long established convention doing the opposite. People tend to do things on automatic, unfortunately. Like, I "upvoted" your comment now in an on-automatic attempt to reply to it, pretty silly, yes? – Cheers and hth. - Alf Nov 03 '11 at 16:48
  • @AlfP.Steinbach: Feel free to automatically upvote any of my stuff anytime. :-P – Emile Cormier Nov 04 '11 at 01:01

6 Answers6

7

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
4

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
4

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
NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

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.

AndersK
  • 35,813
  • 6
  • 60
  • 86
1

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

morechilli
  • 9,827
  • 7
  • 33
  • 54
1

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.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547