C++ has excellent two-way compatibility with the C ABI, but there are some limitations you must observe to write C++ code which C code can call without marshalling at the ABI boundary:
A C++ function may not throw exceptions if it is safe to call from C, and so should always be marked
A C++ function should be annotated with
extern "C"to prevent its symbol being mangled, and thus give it the C rather than C++ ABI.
You cannot use overloading in your
You may only use types in your C++ function declaration for which these traits are both true:
std::is_trivially_copyable_v<T>requires trivial destruction, but NOT trivial construction. This means that C++ can do non-trivial construction of otherwise trivial types)
The above is what the standard officially requires for well defined C and C++ interop. However, all of the three major compilers MSVC, GCC and clang are considerably more relaxed. In those three major compilers, “almost-standard-layout” C++ types work fine in C.
“Almost-standard-layout” C++ types have these requirements:
- No virtual functions or virtual base classes i.e.
std::is_polymorphic_v<T>must be false. This is because the vptrs offset the proper front of the data layout in an unknowable way to C.
- Non-static data members of reference type appear to C as pointers. You must never supply from C to C++ a non-null pointer which is seen as a reference in C++.
- C++ inheritance is seen in C data layout as if the most derived class has nested variables of the inherited types at the top, in order of inheritance.
- Types with non-trivial destructors work fine so long as at least move construction
and assignment is the same as
copying bits like
memcpy(). You just need to make sure instances of the type return to C++, and don’t get orphaned in C. This was referred to in previous pages in this section as “move relocating” types.
Experimental Outcome’s support for being used from C does not meet the current strict requirements, and thus relies on the (very common) implementation defined behaviour just described (it is hoped that future C++ standards can relax the requirements to those just described).
status_code is an almost-standard-layout type,
and thus while it can’t be returned from
extern "C" functions as the compiler
will complain, it is perfectly safe to return from C++ functions to C code on the
three major compilers, as it is an “almost-standard-layout” C++ type if
an “almost-standard-layout” C++ type.