3

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.

2
  • Missing ; in header??? Commented Feb 7, 2018 at 14:02
  • 3
    IINM you need to remove the extern "C" from the C side. The easiest way is to make it a macro that is toggled by #ifdef __cplusplus. Commented Feb 7, 2018 at 14:07

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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?
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, which is why a C compiler will choke on it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.