2

I am trying to use extern "C" to be able to call a C++ class within a different C file. I can build this fine until I actually include the .h in the C file I want to call the C++ class from.

MyClass.cpp

MyClass::MyClass(){};
MyClass::~MyClass(){};

extern "C" void* MyClassInit(){
    return new MyClass();
}

MyClass.h

extern "C" void* MyClassInit();

OK - the above compiles. But now I want to use MyClassInit in another .c file. As soon as I

#include "MyClass.h" in that file I get

error: expected identifier or '(' before string constant in MyClass.h where the externs are defined.

I assume I am missing some "if cplusplus" or another extern or something else very obscure.

J Doe.
  • 299
  • 3
  • 13

1 Answers1

9

There's no extern "C" in C: a C compiler won't understand this and will choke on it. You need to expose this directive to the C++ compiler only. This is why often in such headers you find this instead (a random example e.g. here):

#ifdef __cplusplus
extern "C" {
#endif

... code ...

#ifdef __cplusplus
}
#endif

The C preprocessor will remove the extern "C", keeping the enclosed code only, while for the C++ compiler, the same file will look like

extern "C" {
... code ...
}

Update: A few words on the purpose of the whole extern "C" construct, and why it only appears in C++, as suggested by Justin Randall in the comments. Perhaps the leading reason why this is needed is that it prevents name mangling. This is important when overloaded functions of the same name exist: mangled names are made unique, so these can be distinguished. On the other hand, there is no overloading in C, so no name mangling either and no need for the extern block.

Long story short, a typical C++ compiler would tend to rename a function like void f(), for example, to something like _Z1fv. But the C compiler would look for f and fail. extern "C" makes the former use the same symbol name the latter would expect.

More precise information can be found here.

The Vee
  • 11,420
  • 5
  • 27
  • 60
  • Oh wow.. I finally understand this block of code that's littered throughout my codebase :) Thank you. Just to ask - does the `extern "C"` need to be present in the .cpp file? – J Doe. Feb 07 '18 at 14:17
  • Nice concise answer to a good question. It's also worth mentioning that `extern "C" { }` is simply telling the C++ compiler not to [mangle the function names](https://stackoverflow.com/questions/2937273/questions-about-name-mangling-in-c), which is why a C compiler will choke on it. – Justin Randall Feb 07 '18 at 14:27