gpt4 book ai didi

C++ 插件 : pass object across boundary (emulating it)

转载 作者:行者123 更新时间:2023-11-30 05:47:42 24 4
gpt4 key购买 nike

由于我们不应该跨插件边界传递除普通旧数据结构 [1] 之外的任何其他内容,因此我想出了以下想法来传递对象:

  • 在插件“C”接口(interface)中公开所有公共(public)方法,在应用程序端,将插件包装在一个对象中。 (见下面的例子)

我的问题是:有更好的方法吗?[编辑] 请参阅下面我的编辑,使用标准布局对象可能是更好的解决方案。

这是一个说明这个想法的玩具示例:

我想跨界传递一个 Writer :

class Writer{
Writer();
virtual void write(std::string) = 0;
~Writer(){}
};

但是,我们知道由于兼容性问题不应该直接这样做。这个想法是将 Writer 的接口(interface)公开为插件中的自由函数:

// plugin

extern "C"{
Writer* create_writer(){
return new PluginWriterImpl{};
}

void write(Writer* this_ , const char* str){
this_->write(std::string{str});
}

void delete_writer(Writer* this_){
delete this_;
}
}

并将所有这些函数调用包装在应用程序端的包装器对象中:

// app

class WriterWrapper : public Writer{
private:
Writer* the_plugin_writer; //object being wrapped
public:
WriterWrapper() : the_plugin_writer{ create_writer() }
{}

void write(std::string str) override{
write(the_plugin_writer, str.c_str() );
}

~WriterWrapper(){
delete_writer(the_plugin_writer);
}
};

这导致了很多转发功能。除了 POD 之外没有别的越界,应用程序不知道当前 Writer 的实现来自插件。

[1] 对于二进制兼容性问题。有关详细信息,您可以查看此相关的 SO 问题:c++ plugin : Is it ok to pass polymorphic objects?


[编辑] 看来我们可以通过标准布局跨越边界。如果是这样,这样的解决方案是否正确? (可以简化吗?)

我们想跨越边界传递一个 Writer :

class Writer{
Writer();
virtual void write(std::string) = 0;
~Writer(){}
};

因此我们将从插件中传递一个标准布局对象给应用程序,并将其包装在应用程序端。

// plugin.h
struct PluginWriter{
void write(const char* str);
};

-

// plugin_impl.cpp 

#include "plugin.h"

extern "C"{
PluginWriter* create_writer();
void delete_writer(PluginWriter* pw);
}

void PluginWriter::write(const char* str){
// . . .
}

-

// app
#include "plugin.h"

class WriterWrapper : public Writer{
private:
PluginWriter* the_plugin_writer; //object being wrapped
public:
WriterWrapper() : the_plugin_writer{ create_writer() }
{}

void write(std::string str) override{
the_plugin_writer->write( str.c_str() );
}

~WriterWrapper(){
delete_writer(the_plugin_writer);
}
};

但是,我担心链接器会因为以下原因在编译应用程序时报错:#include plugin.h

最佳答案

在客户端和库端使用具有不同编译器(甚至语言)的 DLL 需要二进制兼容性(又名 ABI)。

无论关于标准布局或 POD,C++ 标准不保证不同编译器之间的任何二进制兼容性。在类成员的布局上没有全面的独立实现规则可以确保这一点(另见 this SO answer在数据成员的相对地址上)。

当然,幸运的是,在实践中许多不同的编译器在标准布局对象中使用相同的逻辑来填充和对齐,使用CPU 体系结构的特定最佳实践或要求(只要不使用打包或外来对齐编译器开关)。因此使用POD/标准布局相对安全(并且作为Yakk正确指出:“如果您信任 pod,则必须信任标准布局。”)

因此您的代码可能有效。其他替代方案,依靠 c++ 虚拟来避免名称混淆问题,似乎也适用于交叉编译器如 this article 中所述.出于同样的原因:在实践中,许多编译器在一个特定的操作系统+架构上使用一种公认的方法用于构建他们的 vtable。但同样,这是实践中的观察结果,并非绝对保证

如果你想为你的库提供交叉编译一致性保证,那么你应该只依赖真正的保证,而不仅仅是通常的保证实践。在 MS-Windows 上,对象的二进制接口(interface)标准COM。 .这是一个全面的C++ COM tutorial .它可能有点老了,但没有其他人有这么多的插图可以理解。

COM 方法当然比您的代码段更重。但这是交叉编译器的成本,甚至是它提供的跨语言合规性保证。

关于C++ 插件 : pass object across boundary (emulating it),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28500533/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com