When to use extern "C"?
Asked Answered
E

6

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?

Encyst answered 3/11, 2011 at 14:1 Comment(7)
Instead of hacking <string.h> to avoid name mangling, use the <cstring> header.Hyman
@AlfP.Steinbach: If you write C++, use <cxxx>. If you write C, use <xxx.h> and compile your code with a C compiler. Mixing languages is not a good idea.Hyman
@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.Rrhoea
@AlexandreC.: your advice is all association and no reasoning. it's dumb.Cyanosis
@AlfP.Steinbach: What if you prefix std:: in front of every function you call from a <cxxx> header? Can there still be portability problems?Rrhoea
@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?Cyanosis
@AlfP.Steinbach: Feel free to automatically upvote any of my stuff anytime. :-PRrhoea
L
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.

Lacey answered 3/11, 2011 at 14:5 Comment(2)
why is there a second #ifdef __cplusplus for?Encyst
@user974191: it's for the closing brace, otherwise the braces would be unbalanced.Lacey
E
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.

Empedocles answered 3/11, 2011 at 14:4 Comment(0)
H
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
Herdsman answered 3/11, 2011 at 14:11 Comment(0)
H
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.

Harriott answered 3/11, 2011 at 14:5 Comment(0)
L
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

Lamasery answered 3/11, 2011 at 14:10 Comment(0)
S
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.

Saying answered 3/11, 2011 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.