使用Rust + Electron開發跨平臺桌面應用 ( 一 )

前言

近段時間學習了Rust,一直想着做點什麼東西深入學習,因爲是剛學習,很多地方都不熟悉,所以也就不能拿它來做編譯器這些,至於web開發,實際上我並不建議拿這個來學習一門語言,大概有幾個方面,一是web開發的套路無非也就那麼幾個,對學習一門語言並不會有多大的幫助。二是web開發大多已經被封裝了很多東西,對學習語言本身其實不利,真的要深入學習的話還是建議從語言本身出發,儘量不要用封裝好的東西,當然,標準庫除外。

爲什麼是Rust + Electron

原因其實很簡單,我不想做太複雜的東西,因爲大部分的精力還是要放在工作上,其次是希望做一個我日常能用的東西,當然現在還沒想好,可能是個音樂播放器,也可能是個天氣展示的app,這樣我就可以每天使用了,這也會更有動力促使我開發好它。

Rust 和 Electron 想必就不用我多介紹了吧,至於爲什麼是這個組合可以查看知乎的這個問題,我贊同的是的方案是

使用 C/Cpp/Rust 開發的核心 + Electron / Qt 開發界面

本期目標

本期的目標非常簡單,將Rust 和 Electron結合起來,使用Rust獲取電腦cpu核數,Electron將數據繪製在界面上展示。

初始化Electron項目

Electron項目的初始化我用的工具是electron-forge,首先我們按照electron-forge的官網介紹來

npm install -g electron-forge

electron-forge init my-new-project

cd my-new-project

electron-forge start

解釋一下,首先我們要安裝electron-forge,這是一個腳手架工具,類似於Vue-cli。
然後我們初始化一個項目,項目名稱爲my-new-project。

需要注意的是這初始化的過程中electron-forge會構建package.json, 然後下載依賴,我第一次下載依賴的時候卡在了electron-runtime,第二次重試的時候就好了。

第二個是electron-forge中的依賴會對Python版本有要求,只能要求Python2,這裏要注意的一點是,我十分不建議使用pyenv來控制Python版本,會出現以下錯誤,我的解決方式是使用virtualenv新建一個Python2 的環境。

Fatal Python error: PyThreadState_Get: no current thread

現在我們來看一下項目結構

clipboard.png

整個項目結構非常簡單,src中是我們的源文件,index.html是界面文件,index.js是界面邏輯文件,大家打開index.js就可以看到一段自動生成的代碼,主要是創建了一個app,以及監聽app的活動,需要注意到的是其中對mac的處理。

app.on('window-all-closed', () => {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

好了,現在讓我們把項目跑起來,在項目目錄下執行electron-forge start命令,稍等一會我們就可以看到界面運行起來了

clipboard.png

初始化Rust項目

在開發之前我們要知道,JS是無法直接運行Rust的,就像JS無法直接運行C++一樣。所以我們需要將Rust打包成Node模塊提供給JS進行調用。所以我們會使用neon來做到這件事,neon的github地址在這裏

首先我們需要安裝neon,注意,neon對python版本也是有要求的,如果你是mac,python版本必須要是Python2.7,不支持Python3,同樣,這裏也會出現上面說過的no current thread問題,所以我們在開發時最好用virtualenv新建一個Python2的環境。

安裝完neon之後我們執行neon new thread-count,新建一個項目。看一下項目結構

clipboard.png

lib是我們最終的導出文件,提供給electron進行調用,native下則是我們的rust代碼,注意,這裏的入口文件是native/src/lib.rs,因爲我們建立的是一個庫而不是一個可執行的應用程序。
讓我們先編譯項目,在文件目錄下執行neon build --release命令。

讓我們進入終端調用一下項目試試:

clipboard.png

成功!到現在我們就成功的將rust寫的代碼封裝成node庫,使得JS可以進行調用了,接下來我們回到上面說過的,將rust的功能更改爲獲取CPU核數,然後將它封裝成一個函數並進行導出。

首先我們要修改Cargo.toml,在[dependencies]下增加一個num_cpus = "1.4.0"的依賴項,
然後修改native/src/lib.rs文件如下

#[macro_use]
extern crate neon;

use neon::prelude::*;

fn thread_count(mut cx: FunctionContext) -> JsResult<JsNumber> {
    Ok(cx.number(num_cpus::get() as f64))
}

register_module!(mut cx, {
    cx.export_function("thread_count", thread_count)
});

修改lib/index.js如下:

var addon = require('../native');

module.exports = addon.thread_count;

然後我們再進行編譯,執行neon build --release命令,然後再進入終端調用這個函數試試

clipboard.png

成功啦,至此,我們就成功的將rust代碼封裝給JS進行了調用。需要注意的是編譯rust的node版本需要與運行electron的node版本一致,否則會出現無法調用的情況。好了,到此第一期就結束了,代碼我會抽空整理到github,以供有需要的同學查看。

最後看一下效果圖吧

clipboard.png

ps: 現在Rust的各項工具和庫都不是很成熟,所以大家再實踐過程中會遇到各種問題,都可以評論到下面大家一起討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章