Application Binary Interface(ABI)
Application Binary Interface(ABI) 是指应用程序在二进制级别上的调用约定和数据布局规则。它决定了一个程序如何与操作系统、库或其他程序的二进制部分交互。ABI 是在编译后的程序之间的接口,而不是在源码层面的接口。
ABI 的主要内容
-
函数调用约定(Calling Conventions)
定义了函数调用时:- 参数如何传递(通过寄存器还是栈)。
- 返回值如何传递。
- 函数调用前后由谁负责保存寄存器(调用者还是被调用者)。
示例:
- 在 x86 平台上,Windows 使用
stdcall
,Linux 使用cdecl
。 - 参数的顺序和方法可能不同,比如先传递右边的参数还是左边的。
-
二进制符号(Symbol Naming)
决定编译后的函数或变量符号在二进制文件中的命名规则。- C 的 ABI 通常直接使用函数名,例如
_add
。 - C++ 的 ABI 通常会进行名称修饰(Name Mangling)以支持函数重载,例如
_Z3addii
。
- C 的 ABI 通常直接使用函数名,例如
-
数据类型的布局和对齐(Data Layout and Alignment)
定义了:- 基本类型(如
int
、double
)的大小。 - 结构体和类的内存对齐规则。
- 字节序(大端或小端)。
- 基本类型(如
-
异常处理(Exception Handling)
规定在不同模块或库之间如何传递和处理异常,特别是跨语言的异常。 -
动态链接(Dynamic Linking)
描述动态链接库(如.so
或.dll
文件)在加载和调用时的接口规则。
ABI 的作用
ABI 的核心作用是确保 二进制兼容性,即:
- 不同的模块(如动态库和主程序)可以协同工作,即使它们是由不同编译器编译的。
- 应用程序能够在某个硬件和操作系统平台上正常运行。
举例:C 和 C++ 的 ABI 差异
在 C 中:
int add(int a, int b) {
return a + b;
}
生成的二进制符号可能是:_add
。
在 C++ 中:
int add(int a, int b) {
return a + b;
}
生成的二进制符号可能是:_Z3addii
(因为 C++ 支持函数重载,需要进行名称修饰)。
因此,C++ 函数如果需要被其他语言或工具调用,就必须使用 extern "C"
以禁用名称修饰,从而遵循 C 的 ABI。
ABI 的重要性
- 跨语言调用:通过一致的 ABI,C 语言库可以被多种语言(如 Python、C#、Rust)调用。
- 跨编译器兼容:遵循相同的 ABI,不同编译器生成的代码可以协同运行。
- 动态链接库的使用:动态库通过 ABI 提供函数接口,供程序运行时调用。
总结
ABI 是程序运行时在二进制层面的契约,它规范了如何正确地调用函数、传递参数和处理数据,使得程序、库和系统可以无缝协作。
注意:该内容由由AIGC提供。