In the cpp core guidelines, there is a (partially incomplete) statement:
I.26: If you want a cross-compiler ABI, use a C-style subset
Reason
Different compilers implement different binary layouts for classes, exception handling, function names, and other implementation details.
Exception
You can carefully craft an interface using a few carefully selected higher-level C++ types. See ???.
A good example of a cross-compiler ABI would be a plugin system. Let's say I want this to be as C++-friendly as possible.
The interface:
class Plugin
{
public:
virtual ~Plugin() {}
enum class Type {A, B, C};
virtual Plugin::Type getType() const = 0;
virtual void doWork() = 0;
};
// C-style for the main plugin entry function
typedef Plugin* (*PluginCreateCallback)();
typedef void (*PluginDestroyCallback)(Plugin*);
extern "C" void pluginMain(PluginCreateCallback* createCb, PluginDestroyCallback* destroyCb);
A plugin implementation (compiled with compiler#1) might look like:
class MyPlugin: public Plugin
{
Plugin::Type getType() const override {return Plugin::Type::A;}
void doWork() {...}
};
Plugin* myCreateCb()
{
return new MyPlugin();
}
void myDestroyCb(Plugin* plugin)
{
delete plugin;
}
extern "C" void pluginMain(PluginCreateCallback* createCb, PluginDestroyCallback* destroyCb)
{
*createCb = &myCreateCb;
*destroyCb = &myDestroyCb;
}
The application implementation (compiled with compiler#2) would contain something like:
handle->pluginMain(&createCb, &destroyCb);
Plugin* plugin = createCb();
plugin->doWork();
destroyCb(plugin);
Questions:
Plugin in a cross-compiler environment? (will it be represented the same in memory?)Plugin::Type enum affect how the Plugin class is represented?Update:
In the "API design for C++" book by Martin Reddy, chapter 12, the exact scenario of using plugin interfaces seems to be specified:
Implementing virtual methods of an abstract base class can insulate a plugin from ABI problems because a virtual method call is usually represented as an index into a class’s vtable. Theoretically, the vtable format can differ between compilers, but in practice this tends not to happen.
From this, I understand that using abstract classes is generally safe between compilers, but definitely not guaranteed by the standard.
I opened an issue on Github to get examples of such exceptions and Herb Sutter's answer was:
Editors call: We don't have a reference to point to, so we agree we should just remove the Exception. Thanks!
This Exception paragraph has now been removed from the guildelines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With