user1559625 user1559625 - 1 month ago 10
C Question

c++ faq 32.8 "pass an object of a C++ class to/from a C function" questions

http://www.parashift.com/c%2B%2B-faq/cpp-objs-passed-to-c.html

The answer is in two parts. First part i guess is till the codes are over.

For the first part, what i see is that the author is using 'C' linkage directive(extern "C") for either functions written in C or C++ functions to be called by C functions (see below), so link will be ok.

extern void c_function(Fred*); // c function
extern Fred* cplusplus_callback_function(Fred*); // c++ function


This make sense.

Then Fred* is passed all the way from main() to c_function() [i guess this is what author/faq says about passing C++ object to C function], and then to cplusplus_callback_function() [object passed back to C++ domain from C function].

So first question, am i understanding the above correctly? So the answer to the faq is just "pass a pointer" of the object?

Second question, what the author explained after the code lost me. He suddenly talk about comparing if pointers are equal, pointer conversion between base and derived etc. What is he trying to say? That pointer after being passed to c_function, lost all its magic? Were it a base class pointer pointing to a derived class, we can do a lot more if it's passed to C++ functions than C function?

Last question, i guess i do not know if C++ code is wrapped in extern "C" directive, the only thing changed is linkage but nothing else? C++ code is still C++, right? if i write all codes in C++, but deliberately wrap some functions in extern "C", what do i lose?

Any help?

Thanks!

Answer

So the answer to the faq is just "pass a pointer" of the object?

There's one more thing to this, which is that #ifndef __cplusplus, you need to

typedef struct Fred Fred;

i.e. forward declare Fred as a struct (note that a struct and a class differ only in default access rights).

What is he trying to say? That pointer after being passed to c_function, lost all its magic?

That a C++ compiler understands inheritance and will convert pointer types prior to doing a comparison. By contrast, a C compiler has no notion of inheritance and actually disallows pointers of different types to a single object, unless at least one of them is void*, char* or unsigned char*. As you can see in the FAQ, even the conversion to void* is subtle in the face of bridging C and C++.

The simple solution is to give the C side of the program only Base pointers. I.e., hide the inheritance from it entirely, if at all possible.

if i write all codes in C++, but deliberately wrap some functions in extern "C", what do i lose?

Overloading. You can't have two functions with C linkage having the same name, i.e.

extern "C" {
    void foo(void);
    void foo(int);
}

is not possible.