Rust+Electronを使ってプラットフォームを跨ぐデスクトップアプリケーションを開発する(二)
2296 ワード
前言
前の記事ではRust+Electronを用いてプラットフォームを跨ぐデスクトップアプリケーションを開発しましたが、Rust+Electronを結合して、Rustを使ってコア業務ロジックを作成し、nodeライブラリをコンパイルしてElectronに提供するUIインターフェースの呼び出しを行いましたが、前の記事で多くの問題が発生しました.特にElectronのバージョンとRustのバージョンは一致しなければなりません.そうしないと、コールが成功しなくなりますので、この状況を変えるために、今日はもう一つの方法でRustのコードをJsに提供して呼び出します.これがFFIです.
FFIは何ですか
FFI(Foreign Function Interface)は他の言語と対話するためのインターフェースです.現実には多くのプログラムが異なるプログラミング言語で書かれているため、必然的にクロス言語の呼び出しに関連します.
1、関数をサービスにし、プロセス間通信(IPC)またはネットワークプロトコル通信(RPC、RESTfulなど)を通じて.
2、直接FFIで呼び出します.
前者は少なくとも2つの独立したプロセスが必要であり、後者は直接に他の言語のインターフェースを本言語に埋め込むので、呼び出し効率は前者より高い.
Rustはシステムレベルのプログラミング言語として、FFIに対しても完璧なサポートを提供しています.
マング
ルーストは重積載をサポートしていますので、関数名はコンパイラで混同されます.c++のように.したがって、関数がコンパイルされた後、関数名には、関数の署名を示す文字列が付いています.このような関数名は、ffi呼出が困難であるため、RUstは関数修飾として「noga」属性を提供している.ガグ属性を持つ関数に対して、ルーストコンパイラは関数名の混淆を行いません.
RUstはデフォルトでRUST用のrlibフォーマットライブラリにコンパイルされています.RUstを動的リンクライブラリまたは静的リンクライブラリにコンパイルするには、指定を表示する必要があります.全部で3つの方法があります.ここでは直接にCago.Tomlファイルに指定します.以下の通りです.
私たちはcargo build命令を実行しています./target/debugディレクトリの下で必要なファイルlibthread_を作成しました.count.dylib
JSはrustのダイナミックリンクライブラリを使用します.
じゃ、私達はどうやってJSでルーストを呼び出してdylibを生成しますか?答えはffi-napiです.私たちはffi-napiというカバンを使ってjsでffiを呼び出します.話は多くなくて、直接コードを見ます.
はい、ここまできて、私達はルーストを動的リンクライブラリにコンパイルしてJSに呼び出すことに成功しました.この方式はいいと思います.関数を導入する方式は醜いですが、nodeバージョンの問題を心配しなくてもいいです.
おわりに
FFIはいい方法だと思いますが、例えばFFIを越える過程で、私達はルーストのタイプ情報をなくして、安全性の問題を引き起こします.もちろんこれも解決方法がないわけではありません.私達はルーストのBoxを使って私達のタイプを包装することができます.これは単独で文章を書くことができます.(まず穴を掘って、いつ思い出したら記入しますか?)
前の記事ではRust+Electronを用いてプラットフォームを跨ぐデスクトップアプリケーションを開発しましたが、Rust+Electronを結合して、Rustを使ってコア業務ロジックを作成し、nodeライブラリをコンパイルしてElectronに提供するUIインターフェースの呼び出しを行いましたが、前の記事で多くの問題が発生しました.特にElectronのバージョンとRustのバージョンは一致しなければなりません.そうしないと、コールが成功しなくなりますので、この状況を変えるために、今日はもう一つの方法でRustのコードをJsに提供して呼び出します.これがFFIです.
FFIは何ですか
FFI(Foreign Function Interface)は他の言語と対話するためのインターフェースです.現実には多くのプログラムが異なるプログラミング言語で書かれているため、必然的にクロス言語の呼び出しに関連します.
1、関数をサービスにし、プロセス間通信(IPC)またはネットワークプロトコル通信(RPC、RESTfulなど)を通じて.
2、直接FFIで呼び出します.
前者は少なくとも2つの独立したプロセスが必要であり、後者は直接に他の言語のインターフェースを本言語に埋め込むので、呼び出し効率は前者より高い.
Rustはシステムレベルのプログラミング言語として、FFIに対しても完璧なサポートを提供しています.
マング
ルーストは重積載をサポートしていますので、関数名はコンパイラで混同されます.c++のように.したがって、関数がコンパイルされた後、関数名には、関数の署名を示す文字列が付いています.このような関数名は、ffi呼出が困難であるため、RUstは関数修飾として「noga」属性を提供している.ガグ属性を持つ関数に対して、ルーストコンパイラは関数名の混淆を行いません.
#[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を動的リンクライブラリまたは静的リンクライブラリにコンパイルするには、指定を表示する必要があります.全部で3つの方法があります.ここでは直接にCago.Tomlファイルに指定します.以下の通りです.
[lib]
name = "thread_count"
crate-type = ["dylib"]
なお、name
は、RUstのパケット構造に適合していなければならず、srcディレクトリの下で見つけることができる.私たちはcargo build命令を実行しています./target/debugディレクトリの下で必要なファイルlibthread_を作成しました.count.dylib
JSはrustのダイナミックリンクライブラリを使用します.
じゃ、私達はどうやってJSでルーストを呼び出して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);
結果は以下の通りですはい、ここまできて、私達はルーストを動的リンクライブラリにコンパイルしてJSに呼び出すことに成功しました.この方式はいいと思います.関数を導入する方式は醜いですが、nodeバージョンの問題を心配しなくてもいいです.
おわりに
FFIはいい方法だと思いますが、例えばFFIを越える過程で、私達はルーストのタイプ情報をなくして、安全性の問題を引き起こします.もちろんこれも解決方法がないわけではありません.私達はルーストのBoxを使って私達のタイプを包装することができます.これは単独で文章を書くことができます.(まず穴を掘って、いつ思い出したら記入しますか?)