我经常使用该技术将我的高性能 C++ 类包装为一个薄的 C 层,我将其编译为共享库,然后用其他编程语言(例如 Python)加载它们。
根据我在这里和那里的阅读,我了解到要使它起作用的唯一要求是让函数接口(interface)仅使用 native 类型或这些类型的结构。 (因此,int
和 long
、float
、double
等以及它们的任意级别的指针)。
我的问题是:假设完整 ABI compatibility在各种编译器之间,这是我要实现与共享库的完整 API 兼容性的唯一要求吗?
为什么不能移植C++库?这是我的理解:
情况 1:考虑 std::string
类型。它在内部包含一个 char*
空终止字符串和一个大小整数。 C++ 标准并没有说明哪一个应该先出现(对吧?)。这意味着如果我将 std::string
放在函数接口(interface)上,两个不同的编译器可能会以不同的顺序排列它们,这是行不通的。
案例 2:考虑为具有虚方法的类继承和虚表。 C++ 标准不要求 vtable 指针必须去的地方的任何特定位置/顺序(对吗?)。它们可以位于类的开头,位于任何其他变量之前,也可以位于类的末尾,位于所有其他成员变量之后。同样,在函数上连接此类将不一致。
我的第一个问题之后的另一个问题:这个问题不会也发生在函数调用中吗?还是编译成二进制后就什么都不重要了,类型就没有意义了? RTTI 元素是否会导致问题,例如,如果我将它们放在 C 包装器接口(interface)中?
最佳答案
没有 C++ ABI 的部分原因是没有 C ABI。正如 Bjarne Stroustrup ( source ) 所述:
The technical hardest problem is probably the lack of a C++ binary interface (ABI). There is no C ABI either, but on most (all?) Unix platforms there is a dominant compiler and other compilers have had to conform to its calling conventions and structure layout rules - or become unused. In C++ there are more things that can vary - such as the layout of the virtual function table - and no vendor has created a C++ ABI by fiat by eliminating all competitors that did not conform. In the same way as it used to be impossible to link code from two different PC C compilers together, it is generally impossible to link the code from two different Unix C++ compilers together (unless there are compatibility switches).
缺少 ABI 为编译器实现提供了更多自由,并允许将语言传播到多种不同类型的系统。
在 Windows 上,有一些特定于平台的依赖项依赖于编译器输出结果的方式,一个例子来自 COM需要以特定方式布置纯虚拟接口(interface)的地方。所以在 Windows 上,大多数编译器至少会同意这一点。
Windows API 使用 stdcall
调用约定,因此在针对 Windows API 进行编码时,对于如何将参数传递给函数有一套固定的规则。但这同样取决于系统,并且没有什么可以阻止您编写使用不同约定的程序。
关于c++ - C++ 二进制代码能否通过 native C 接口(interface)变得可移植?有什么限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42361693/