资讯专栏INFORMATION COLUMN

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

forrest23 / 3672人阅读

摘要:前言在上一篇文章使用开发跨平台桌面应用一中,我们将结合起来,使用编写核心业务逻辑,并编译成库提供给的界面调用,但是在上一篇文章中发现遇到了很多问题,尤其是的版本和编译出来的版本必须要一致,否则会无法调用成功,这就很坑了,所以为了改变这一情况

前言

在上一篇文章使用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

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);

结果如下:

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

结语

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101475.html

相关文章

  • 使用Rust + Electron开发平台桌面应用 ( 一 )

    摘要:所以我们需要将打包成模块提供给进行调用。安装完之后我们执行,新建一个项目。需要注意的是编译的版本需要与运行的版本一致,否则会出现无法调用的情况。 前言 近段时间学习了Rust,一直想着做点什么东西深入学习,因为是刚学习,很多地方都不熟悉,所以也就不能拿它来做编译器这些,至于web开发,实际上我并不建议拿这个来学习一门语言,大概有几个方面,一是web开发的套路无非也就那么几个,对学习一门...

    DrizzleX 评论0 收藏0
  • 前端每周清单第 43 期:2017 JavaScript 回顾、Rust 与 WebAssembly

    摘要:杨冀龙是安全焦点民间白帽黑客组织核心成员,被浪潮之巅评为中国新一代黑客领军人物之一他在本文中依次分享了对于黑客的定义如何从黑客成为一名安全创业者技术创业踩过的坑给技术创业者建议等内容。 showImg(https://segmentfault.com/img/remote/1460000012377230?w=1240&h=796); 前端每周清单专注前端领域内容,以对外文资料的搜集为...

    xorpay 评论0 收藏0
  • 用JS开发平台桌面应用,从原理到实践

    摘要:导读使用开发客户端程序已经有一段时间了,整体感觉还是非常不错的,其中也遇到了一些坑点,本文是从运行原理到实际应用对进行一次系统性的总结。一桌面应用程序桌面应用程序,又称为程序,但是和程序也有一些区别。就开发速度方面,比原生编译技术要快一些。 导读 使用Electron开发客户端程序已经有一段时间了,整体感觉还是非常不错的,其中也遇到了一些坑点,本文是从【运行原理】到【实际应用】对Ele...

    mj 评论0 收藏0
  • 使用Electron 构建是自己的桌面快捷应用

    摘要:是一款帮助开发者实现跨平台桌面开发的平台。开发者只需要使用即可开发属于自己的桌面应用。下面我来介绍下自己开发的一个小的应用,主要用来简化进入终端的步骤。增加的时候弹框选择一个想要打开的应用,可以添加自己的命令,比如甚至启动之类的。 electron 是一款帮助开发者实现跨平台桌面开发的平台。开发者只需要使用javascript html css即可开发属于自己的桌面应用。 所以说假如你...

    Gilbertat 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<