It is possible that C-linked functions return objects that cannot be expressed in C while they can be processed in C. According to my copy of Design and Evolution of C ++ (section 11.3.3):
We examined several alternatives to type binding schemes before deciding what was actually added to the language [Stroustrup, 1988]: ...
- provide type binding only for functions that cannot be C functions, because they have types that cannot be expressed in C ....
A function declared by C-C binding still has the semantics of C ++ invocation. That is, formal arguments must be declared, and the actual arguments must comply with C ++ compliance rules and ambiguity rules .... If we provided special services for C, we would be required to add an unlimited set of language calling conventions for C ++ compilers [for links to Pascal, Fortran, PL / I, etc.] ....
Linking, interlanguage calls, and interlanguage transfer of objects are inherently difficult problems and have many implementation-related aspects .... I expect that we have not heard the last of this question.
That is, C ++ communication is not based on whether the types involved are valid types of C. This is an intentional design decision. This allows you to create a DLL compiled in C ++, but which can be used with C through the header:
// in the header struct Foo; // forward declaration #ifdef __cplusplus extern "C" { #endif struct Foo* create_foo(); void destroy_foo(struct Foo*); void foo_bar(struct Foo*); #ifdef __cplusplus } // extern "C" // now declare Foo struct Foo { void bar(); }; #endif // in the implementation file #include <iostream> extern "C" { Foo* create_foo() { return new Foo(); } void destroy_foo(Foo* f) { delete f; } void foo_bar(Foo* f) { f->bar(); } } void Foo::bar() { std::cout << "Foo::bar() called\n"; }
Note the calls to new , delete and std::cout . All this requires C ++ runtime. Therefore, the implementation file must be compiled with C ++, but since functions have a C link, the header can be used with C or C ++.
So how do you get Foo in C? In this case, you will not do this, because there is no way to fully declare it in the header so that C understands. Instead, C only sees the forward declaration, which creates an incomplete type. C does not know how large an incomplete type is, so C functions cannot create it or work with them directly, but C knows how large a pointer to an incomplete type is, so C can work with a pointer to an incomplete type. You can get a lot more creativity and actually create POD types in C ++, with which you can work directly in C.
As long as you use only Foo* in C, you donโt need to actually define the structure of Foo in C. It so happens that APR uses a similar project ("Creating an APR Type", I could not find a better link).