C++ ABI Compatibility
Contents
What is an ABI
An Application Binary Interface (ABI) defines how binary components interact at runtime. ABIs include calling conventions, exception handling, type layouts, and more. Since C++ does not support a standardized ABI, different compilers may produce incompatible binaries.
For stability, it is recommended to compile C++ code using the same toolchain. If interoperability is necessary, use C interfaces or COM.
For more information on ABI, see Application Binary Interface
ABI Compiler Support
RAD Studio compiler supports the following:
- Win64 calling convention
COFF
for object files and DLLs.
C Code Compatibility
When writing in Plain Old C (POC), the following works seamlessly:
- POC libraries
- DLLs with a POC interface: functions exported via
extern “C”
)
```c
extern "C" {
__declspec(dllexport) int add_numbers(int a, int b);
}
```
C++ Code Compatibility
C++ has no standardized Application Binary Interface (ABI); therefore, mixing compilers can be risky. It is recommended to build using the RAD Studio compiler. The following are some of the risks explained.
Name Mangling Differences
The RAD Studio compiler uses Itanium name mangling], which is the cross-platform standard. Vendors may use different toolchains that can make things different; for example, MSVC uses its own mangling scheme. Therefore, even if the COFF
format matches, the symbols may not be linked.
Standard Library (STL) Incompatibilities
RAD Studio uses LLVM’s libc++, a cross-platform STL. Vendors may use different toolchains, which can make things different. For example, MSVC uses its own STL, such as: msvcprt.lib
, msvcp140.dll
, and more.
This means that the implementation of, say, a std::vector
is different, so it is not possible to link to code using a std::vector
because, while the user-facing name is the same, the underlying implementation, layout, etc, is different. This is true for all C++ types, with std::vector being an example.
Runtime Behavior Differences
ABI mismatches can occur even if linking succeeds. It is not guaranteed that the ABI is the same. Some causes are mentioned below:
- Incorrect memory layout. In memory layout may be different inside types.
- Undefined behavior in exception handling.
- Runtime instability that may be hard to track down.
Using COM
If rebuilding is not an option, you can wrap it in a COM object using the steps below.
COM provides a stable binary interface across compilers.
- Use COM interfaces to expose your C++ functionality.
- Use
IDL
to define a contract between components. - Clients can consume the COM object regardless of the compiler used.