前言
受到2022年“谷歌使用Rust重写Android系统且所有Rust代码的内存安全漏洞为零” [1] 的启发,最近笔者怀着浓厚的兴趣也顺应Rust 的潮流,尝试着将一款C语言开发的基础软件转化为 Rust 语言。本文的主要目的是通过记录此次转化过程中遇到的比较常见且有意思的问题以及解决此问题的方法与大家一起做相关的技术交流和讨论。
问题描述
本文将记录转化过程中遇到的另外一个问题。该问题是由已经转化完成的 Rust 代码使用到软件中引入的第三方软件包和链接库所导致的。设想这样一个场景:Rust 项目中完成某一个功能点需要用到一个或多个第三方软件包和链接库。这显然是很常见的用户场景,但是由于用户环境不同,用户安装的第三方软件包和链接库的版本不同,使得转化后的 Rust 代码必须要做适当的兼容处理。
这里所说的用户的环境不同,可以理解为芯片指令集的平台不同,如 Intel x86 以及国产的 ARM 麒麟服务器。当然更常见的情形是芯片平台相同,但是存在操作系统层面第三方软件包和链接库安装的差异,如 x86 下的 Ubuntu 和 CentOS 中用户安装了不同版本的第三方软件包和链接库等。
事实上,即使排除所有平台和系统层面的差异,由于用户安装了该基础软件所依赖的不同版本的第三方软件包和链接库,然而这些第三方软件包或者链接库由于自身的演进导致不同版本之间存在较大差异(可能实现相同功能的函数和函数签名都有千差万别),这给我重写该软件的工作带来了一些挑战。基于上述说明,在完成重写该基础软件的过程中如何使得转化后的 Rust 代码能兼容该基础软件所依赖的主流第三方软件包和链接库则是我遇到的最大挑战。需要说明的是这里的第三方软件包和链接库可能是基于 Rust 语言开发的,也可能是基于 C 语言开发的。
解决方案
对于此问题的解决方案需要使用 Rust FFI(Foreign Function Interface) [1],这基本上是没有太大争议的。因为在本次软件重写过程中我遇到的场景是:对于不同版本的链接库使用哪个版本的函数取决于用户的安装运行时环境,所以除了 Rust FFI,在代码适配上我还考虑了使用 Rust features [2] 机制。
下面我简化了一下场景和解决方案,同时我把样本代码放到了我的 github [3] 里,欢迎大家一起交流。如样本代码所示,my-rust-bi