命名空间是否会破坏ABI?

3
我已经搜索了一些关于DLL的C++(类似COM)ABI接口的文章,例如:"Exporting C++ classes from a DLL""Binary-compatible C++ Interfaces",它们非常好而且有用,但是它们没有讨论命名空间。
命名空间会破坏ABI吗?
namespace Foo {

    class Listener {
        virtual void e1() = 0;
        virtual void e2() = 0;
    };

    class Interface {
        virtual void setListener(Listener*) = 0;
        virtual int f1() = 0;
        virtual int f2() = 0;
    };

}

extern "C" Foo::Interface* SOME_API createFooInterface();

我不知道,它能工作吗?


抱歉,我的表达不够清晰,我的英语写作能力不是很好。

在我的代码片段中,extern "C" 防止了 C++ DLL 导出的名称混淆,名称混淆在不同的 C++ 编译器之间是不兼容的,上面提到的两篇文章都在讨论这个问题。

我所说的“破坏 ABI”是指: 我可以在 MSVC 中实现这个,我可以为我的 C++ 接口类使用命名空间,我可以从这段代码中导出一个 DLL,但我不确定这个接口仍然是 ABI - 不同编译器之间的二进制兼容接口,这不是关于两个命名空间,而是关于两个或多个编译器。


1
由于复杂性,我无法尝试每个编译器,而一次尝试是不够的。我不知道是否有关于此的某些事实标准。 - amanjiang
如果你的示例实际上允许那个测试,我可以告诉你半打编译器的结果,即使它不是标准的章节和诗歌,这也应该是一个很好的开始。既然没有,那就把它看作是你的问题还有待改进的微妙提示,即需要更多的研究工作。或者换句话说:在你的想法中,Foo::Interface *应该如何被展开为“C”链接,即没有名称修饰,并且仍然可以与例如Bar::Interface *区分开来?createFooInterface()函数如何返回一个C++构造(一个命名空间类型)的C函数? - DevSolar
@amanjiang:测试对于证明某些东西可行是很有效的,但它们不能帮助你证明某些东西将总是有效。在这种情况下,DevSolar有一点道理:C++ 命名空间的更改将影响 C++ ABI。但我不明白你在讨论 C++ ABI 时为什么要写 extern "C"。那样做没有意义。 - MSalters
命名空间是编译器的概念,在编译后消失。谈论ABI并不合适,这里适用C++规则。虚拟分派表可以在C中模拟,只是没有太多乐趣。工具可以帮助,例如COM世界中的MIDL可以从IDL自动生成C声明。 - Hans Passant
由于二进制兼容性,名称修饰与 DLL 导出不兼容。我认为 "extern C" 是一个纯 C++ 语法,它只涉及链接。在 MSVC 中,extern "C" 函数可以返回命名空间接口,而且你也可以将其放入命名空间中。但我的问题是,我不确定它是否能够在所有与 COM 兼容的编译器中正常工作。 - amanjiang
显示剩余5条评论
1个回答

2

必须这样做。由于两个函数除了它们的命名空间之外可能是相同的,因此ABI必须能够区分它们。也就是说,它们必须具有唯一的名称。因此,更改命名空间会删除一个函数并引入另一个函数,而编译器不知道两者之间的关系。编译器不会阅读您的Git或SVN注释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接