简体   繁体   English

C ++中安全的交叉编译器ABI?

[英]Safe cross-compiler ABI in C++?

In the cpp core guidelines, there is a (partially incomplete) statement : 在cpp核心指南中,有一个(部分不完整) 声明

I.26: If you want a cross-compiler ABI, use a C-style subset I.26:如果你想要一个交叉编译器ABI,请使用C风格的子集

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. 您可以使用一些精心挑选的更高级别的C ++类型来精心设计界面。 See ???. 见???。

A good example of a cross-compiler ABI would be a plugin system. 交叉编译器ABI的一个很好的例子是插件系统。 Let's say I want this to be as C++-friendly as possible. 假设我希望这可以像C ++一样友好。

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: 插件实现(使用编译器#1编译)可能如下所示:

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: 应用程序实现(使用编译器#2编译)将包含以下内容:

handle->pluginMain(&createCb, &destroyCb);
Plugin* plugin = createCb();
plugin->doWork();
destroyCb(plugin);

Questions : 问题

  • is it safe to use classes like Plugin in a cross-compiler environment? 在交叉编译环境中使用Plugin这样的类是否安全? (will it be represented the same in memory?) (它会在内存中表示相同吗?)
  • will extending the Plugin::Type enum affect how the Plugin class is represented? 将扩展Plugin::Type枚举会影响插件类的表示方式吗?
  • more generally, what would be those "carefully selected higher-level C++ types"? 更一般地说,那些“精心挑选的高级C ++类型”是什么?

Update : 更新

In the "API design for C++" book by Martin Reddy, chapter 12, the exact scenario of using plugin interfaces seems to be specified: 在Martin Reddy的第12章“API设计for C ++”一书中,似乎指出了使用插件接口的确切场景:

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. 实现抽象基类的虚方法可以使插件与ABI问题隔离,因为虚方法调用通常表示为类的vtable的索引。 Theoretically, the vtable format can differ between compilers, but in practice this tends not to happen. 从理论上讲,vtable格式在编译器之间可能有所不同,但实际上这种情况往往不会发生。

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: 在Github上打开了一个问题来获取这些异常的例子,而Herb Sutter的答案是:

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. 例外现已从guildelines中删除

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM