3

PLEASE before closing as dupe, read the question & see why it is different (hint: it's the C compiler)

I have Googled and found many, many, explanations of how a C function can call a C++ member function.

They all look similar to the accepted answer to this question, from a very high rep member.

It says

In a header file, put

extern "C" void* MyClass_create() {
   return new MyClass;
}
extern "C" void MyClass_release(void* myclass) {
   delete static_cast<MyClass*>(myclass);
}
extern "C" void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
   static_cast<MyClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}

and, in the C code, put

void* myclass = MyClass_create();
MyClass_sendCommandToSerialDevice(myclass,1,2,3);
MyClass_release(myclass);

That seems straightforward, but what I don't understand is that the header file is going to have to reference MyClass (never mind that static_cast), but I want to compile my C code with a C compiler (gcc), not a C++ compiler (g++).

It won't work. How can I call a C++ member function from C code - which is compiled with a C compiler?

Community
  • 1
  • 1
Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551
  • 5
    The other answer doesn't say *"In a header file, put"*. It says *"Then inside C++ perform the function call:*". The C compiler can only process the declarations, not the function definitions. – Bo Persson Apr 21 '17 at 08:29
  • 1
    Put only the declarations in the header file, the definitions of those functions need to be compiled by the C++ compiler. – Daniel Jour Apr 21 '17 at 08:30
  • @BoPersson Sorry, but I am a Mawg of very little brain. Can you please explain it as if to a five year old? Surely, sooner or later, the C code is referencing the name of a class (or even the class keyword)? I can see how it works if you compile the C code with a C++ compiler, but don't understand how to do it with a C compiler :-( – Mawg says reinstate Monica Apr 21 '17 at 08:32
  • 3
    The question you linked is marked as a duplicate of another question where there is a detailed example explaining what should be put into the header and what into the C++ definition – UnholySheep Apr 21 '17 at 08:37
  • 2
    Ok, I didn't read all of your question, sorry. You can compile your C code with a C compiler, but will have to compile the C++ code with a C++ compiler. The C compiler can understand `void* MyClass_create();` and call that function. If the C++ compiler sees the function as `extern "C" void* MyClass_create();` it will make the call from C work. – Bo Persson Apr 21 '17 at 08:37
  • @UnholySheep That referenced question was a greta help. A pity he doesn't give the C code, but I guss it includes only api.hpp Thanks (+1) – Mawg says reinstate Monica Apr 21 '17 at 08:48
  • 1
    The key point here is that you cannot call the member function with a C compiler. Maybe I should have been clearer, you implement a C++ function with a C interface that is callable from C, and that implementation does the C++ call. Note that it is inherently impossible to call a C++ member function from a C compiler, the compiler would have to parse the class and understand it, know how to call a member function... be a C++ compiler. – David Rodríguez - dribeas Apr 21 '17 at 10:31

1 Answers1

5

You should do the following in C++:

In a C-compatible header file, e.g. interface.h, write:

#if defined(__cplusplus)
extern "C" {
#endif

void* MyClass_create();
void MyClass_release(void* myclass);
void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id);

#if defined(__cplusplus)
}
#endif

and in a source file, e.g. interface.cpp, put

/*extern "C"*/ void* MyClass_create() {
    return new MyClass;
}
/*extern "C"*/ void MyClass_release(void* myclass) {
    delete static_cast<MyClass*>(myclass);
}
/*extern "C"*/ void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
    static_cast<MyClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}

Now, compile these either as part of the original C++ library, or a separate C++ library. You should be able to include the above .h file in your pure C programs and link them against the library.

yzt
  • 8,873
  • 1
  • 35
  • 44