Aria曾断言解析C基本上是不可能的,但有人说其实有很多工具可以读取C头文件,比如rust-bindgen 。事实果真如此吗?其实不然 。
bindgen使用libclang来解析C和C++头文件 。要修改bindgen搜索libclang的方式,请参阅clang-sys文档 。关于bindgen如何使用libclang的更多细节,请参阅bindgen用户指南 。任何花费大量时间试图快速解析C(++)头文件的人都会很快放弃,然后让一个C(++)编译器来做这件事 。请记住,有意义地解析C头文件不仅仅是解析:你还需要解决#includes、typedefs和macros的问题!所以现在不仅要实现所有相关功能,还要实现所有平台的头文件解析逻辑,并且还需要想方设法找到DEFINED!
就拿Swift来说,它在C互操作和资源方面拥有绝对优势,它是由苹果开发的一门编程语言,有效取代了Objective-C,成为在其平台上定义和使用系统API的主要语言 。在这样做的过程中,它比其他任何人都更进一步实现了ABI稳定性和设计概念 。
它也是Aria见过的最支持FFI的语言之一 。它可以本地导入(Objective-)C(++)头文件,并产生一个漂亮的本地Swift接口,其类型在边界自动 "桥接 "到它们的Swift对等项(由于类型具有相同的ABI,所以通常是透明的) 。
Swift也是由苹果公司中许多构建和维护Clang和LLVM的人开发 。这些人都是C及其衍生品方面的世界顶级专家 。Doug Gregor就是其中之一,他曾表达了对C FFI的看法:
文章插图
所有这些都是Swift内部使用Clang来处理 C(++) ABI的原因 。这样一来,我们就不会去追着Clang增加的每一个影响ABI的新属性 。可以看出,即使是Swift也不想花时间解析C(++)头文件 。那么,如果你绝对不想让C编译器在编译时解析和解决头文件,你该怎么做呢?
你需要手工翻译!
int64_t
? 还是写i64. long
…?什么是long?文章插图
C实际上没有ABI
好吧,这没有什么好惊讶的:C语言中的整数类型,为了 “可移植性”而被设计成摇摆不定的大小,实际上大小也是不稳定的 。我们可以认为CHAR_BIT很奇怪,但这也不能帮助我们了解
long
的大小和对齐方式 。有人说每个平台都有标准化的调用约定和ABI,确实有,而且它们通常定义了C中关键原语的布局(并且有些不只是用C类型来定义调用约定,这里侧眼于AMD64 SysV) 。
还有一个棘手的问题:架构并没有定义ABI,操作系统也是 。我们必须在一个特定的目标三元组上全力以赴,比如 “x86_64-pc-windows-gnu”(不要和 "x86_64-pc-windows-msvc "混淆) 。经过测试,一共有176个三元组 。
> rustc --print target-list
aarch64-apple-darwin
aarch64-apple-IOS
aarch64-apple-ios-macabi
aarch64-apple-ios-sim
aarch64-apple-tvos
...
armv7-unknown-linux-musleabi
armv7-unknown-linux-musleabihf
armv7-unknown-linux-uclibceabihf
...
x86_64-uwp-windows-gnu
x86_64-uwp-windows-msvc
x86_64-wrs-vxworks
>_
这实在是有太多ABI了,因为测试中甚至没有用到所有不同的调用约定,如stdcall vs fastcall或aapcs vs aapcs-vfp 。但至少所有这些ABI和调用约定之类的东西,都可以一种方便使用的机器可读格式获得 。至少主流的C编译器在特定目标三元组的ABI上达成了一致! 当然有一些奇怪的jank C编译器,但Clang和GCC不是:
> abi-checker --tests ui128 --pairs clang_calls_gcc gcc_calls_clang
...
Test ui128::c::clang_calls_gcc::i128_val_in_0_perturbed_small passed
Test ui128::c::clang_calls_gcc::i128_val_in_1_perturbed_small passed
Test ui128::c::clang_calls_gcc::i128_val_in_2_perturbed_small passed
Test ui128::c::clang_calls_gcc::i128_val_in_3_perturbed_small passed
Test ui128::c::clang_calls_gcc::i128_val_in_0_perturbed_big failed!
test 57 arg3 field 0 mismatch
caller: [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 3A, 3B, 3C, 3D, 3E, 3F]
callee: [38, 39, 3A, 3B, 3C, 3D, 3E, 3F, 40, 41, 42, 43, 44, 45, 46, 47]
Test ui128::c::clang_calls_gcc::i128_val_in_1_perturbed_big failed!
test 58 arg3 field 0 mismatch
caller: [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 3A, 3B, 3C, 3D, 3E, 3F]
callee: [38, 39, 3A, 3B, 3C, 3D, 3E, 3F, 40, 41, 42, 43, 44, 45, 46, 47]
...
392 passed, 60 failed, 0 completely failed, 8 skipped
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 桶排序算法
- 司马小七说说代理Proxy
- docker容器与传统虚拟机对比
- 带你了解什么是Web 2.0 和 Web 3.0
- 泡红茶用冷水还是热水,红茶是半发酵还是发酵
- 视网膜显示的意义是什么
- 切除子宫肌瘤的危害
- 羊水少多久复查一次
- 子宫肌瘤7厘米严重吗
- 宫颈粘黏症状