Can an extern "C"
function accept or return C++-specific data types, such as references, pointers-to-members, or non-POD classes (by value)? I cannot find anything in the C++ standard that forbids this. Logically, I would expect the standard to say something about it, as the C ABI is not necessarily suitable for passing such types around.
The reason for me wanting to use C linkage has nothing to do with C compilers. The function is called only from C++ code. I just want to export unmangled function names from my dynamic libraries.
A silly code example:
class Foo {
public:
virtual void doit() = 0;
};
class Bar : public Foo {
public:
void doit() { std::cout << "Bar" << std::endl; }
};
extern "C" Foo& getFoo() { static Bar bar; return bar; }
extern "C" Bar getBar() { return Bar(); }
This compiles with GCC on Linux, and works as expected. Should it, standard-wise?
The question is a follow-up to a discussion in the comments to this question.
Update I have tested this with the Comeau compiler, it didn't complain.
I don't have a definitive answer to this but extrapolating from Wikipedia, I'd say that this isn't guaranteed to work. The article (I don't have a copy of the standard) says
extern "C"
specs both the mangling and the ABI. C ABIs presumably don't spec non-C types so you're off in unspec'd behavior. (The article also cites cases where the C and C++ ABIs are different though that doesn't seem like it'd be an issue here.)So while I imagine it might work in virtually all cases, I doubt you could cite chapter and verse from the standards that say it must. I'd not be terribly surprised to see a compiler that refused to compile it.
5.2.2 Function call [expr.call]
So if the type of your function at the call point (ie the type of the function you are calling) is different from the type of the function at the definition point the result is undefined.
7.5 Linkage specifications (Paragraph 1) [dcl.link]
From this we see that the language linkage is part of the type of the function. So both call site and call implementation must have exactly the same language linkage.
7.5 Linkage specifications (Paragraph 9) [dcl.link]
Since C does not support C++ types, No C++ objects can be passed across the interface in a meaningful way. The function can not have C language linkage and be passed C++ objects. Thus we are breaking the type rules defined above.
But: Not only do we have to consider the layout of the object but how the object is passed/returned. Are values passed on the stack or by register this is all defined by the ABI and since C/C++ have different API there is no guarantee how the object is passed from one to the other or that the expectations of function cleanup are the same.
Have you considered using a .def file, which will allow you to export the decorated-named-functions by different names? This way you can enjoy the benefits of overloading, and at the same time give your functions "friendly" names as you like.
According to section 7.5.9 Linkage specifications (c++11 draft) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
"Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved."