使用 Rust + Electron 开发跨平台桌面应用 (二)

本贴最后更新于 1818 天前,其中的信息可能已经事过景迁

前言

在上一篇文章使用 Rust + Electron 开发跨平台桌面应用 ( 一 )中,我们将 Rust + Electron 结合起来,使用 Rust 编写核心业务逻辑,并编译成 node 库提供给 Electron 的 UI 界面调用,但是在上一篇文章中发现遇到了很多问题,尤其是 Electron 的版本和 Rust 编译出来的版本必须要一致,否则会无法调用成功,这就很坑了,所以为了改变这一情况,今天我们将使用另一种方式将 Rust 的代码提供给 Js 进行调用,这就是 FFI。

FFI 是什么

FFI(Foreign Function Interface)是用来与其它语言交互的接口,由于现实中很多程序是由不同编程语言写的,必然会涉及到跨语言调用,这时一般有两种解决方案:

1、将函数做成一个服务,通过进程间通信(IPC)或网络协议通信(RPC, RESTful 等);

2、直接通过 FFI 调用。

前者需要至少两个独立的进程才能实现,而后者直接将其它语言的接口内嵌到本语言中,所以调用效率比前者高。

Rust 作为系统级编程语言,也是对 FFI 提供了完善的支持。

mangle

由于 rust 支持重载,所以函数名会被编译器进行混淆,就像 c++ 一样。因此当你的函数被编译完毕后,函数名会带上一串表明函数签名的字符串。
这样的函数名为 ffi 调用带来了困难,因此,rust 提供了#[no_mangle]属性为函数修饰。 对于带有#[no_mangle]属性的函数,rust 编译器不会为它进行函数名混淆, 如:

#[no_mangle]
pub extern fn test() {}

下面我们来编写一个 thread_count.rs,其实跟寻常的 rust 代码没有什么区别:

#[no_mangle]
pub extern fn threadcount(x: i32) -> i32 {
    let result: i32 = num_cpus::get() as i32;
    return result * x;
}

指定库类型

rust 默认编译成 rust 自用的 rlib 格式库,要让 rust 编译成动态链接库或者静态链接库,需要显示指定,一共有三种方式,我这里采用的是直接在 Cargo.Toml 文件中指定,如下:

[lib]
name = "thread_count"
crate-type = ["dylib"]

需要注意的是 name,必须符合 rust 的包结构,能够在 src 目录下找到。

我们执行 cargo build 命令,可以看到,在/target/debug 目录下生成了我们需要的文件 libthread_count.dylib

clipboard.png

JS 使用 rust 的动态链接库

那么我们要如何在 JS 中调用 rust 生成 dylib 呢?答案就是 ffi-napi,我们使用 ffi-napi 这个包来在 js 中调用 ffi,话不多说,直接看代码

let ffi = require('ffi-napi');
let path = require('path');

let threadCount = ffi.Library(path.join(__dirname, './target/debug/libthread_count'), {
    threadcount: ['int', ['int']]
});

let result = threadCount.threadcount(12);
console.log("thead_count: " + result);

结果如下:

clipboard.png

好了,到此为止,我们就成功的将 rust 编译成动态链接库给 JS 调用了,这种方式是我觉得比较好的一种方式,虽然引入函数的方式比较丑,但是我们不用担心 node 版本的问题。

结语

虽然 FFI 是一种我认为比较好的方式,但是它也不是完美无缺的,例如,在跨越 FFI 的过程中,我们会丢失 rust 的类型信息,从而引发安全性问题,当然这也不是没有解决办法,我们可以使用 rust 的 Box 来包装我们的类型,这个可以单独开一篇文章来讲述,就不展开了(先挖个坑,哪天想起来再填)

  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    57 引用 • 22 回帖
  • FFI
    1 引用
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...