GoとRustが敵ではなく、友人である理由

プログラミング言語に対する神聖な戦争は長い間繰り広げられます。 それぞれに長所と短所があります。 特定のタスクで1つの言語が別の言語に負ける例が常にあります。 それらのいくつかは、1つのプログラムで並んで共存できます。 この投稿では、GoとRustを1つに接続する方法を説明します。


この投稿は、 GoとRustがライバルはない 理由と、GoとRustがライバルではなく、血なまぐさい敵に対する答えです。

Rustとgoには多くの違いがあります。 メモリ管理への異なるアプローチ、異なる祖先、最終的に異なる目標。 それらのスコープは部分的にのみ重複しています。 rustが安全なメモリ管理を重視する場合は、コードの可読性を改善しようとします。

しかし、言語と類似点があります。 両方の言語がコンパイルされます。 両方とも、実績のあるベストプラクティスを取り入れようとしています。 そして最も重要なことは、行くと錆が共通の友人を持っています。 最も古い言語の1つ。 おそらく最も一般的でクロスプラットフォームです。 C言語:どちらにもコードを呼び出すためのツールがあります。 そのため、リンク段階でそれらを結合して、お互いの機能を引き出そうとする人はいません。

さびから始めましょう


さびコードを作成する前に最初にすべきことは、貨物パッケージを記述することです。 goは実行可能ファイルのみを作成できるため、rustコードは静的ライブラリである必要があります。 これを行うには、Cargo.tomlファイルを作成します。
[package] name = "hello" version = "0.1.0" autors = ["Lain-dono <lain.dono@gmail.com>"] [lib] name = "hello" path = "lib.rs" crate-type = ["staticlib"] [dependencies] libc = "0.1.8" 

packageセクションはパッケージに関するメタ情報を記述し、 libセクションはビルドの方法と方法を記述し、 dependenciesセクションは依存関係を管理します。 標準Cライブラリのみに依存します。 結果は、貨物に転送されたキーに応じて/target/debugまたは/target/releaseフォルダーに追加されます。
今、コードの番です。 まず、必要なものをインポートします。
 extern crate libc; use std::ffi::{CStr, CString}; 

次に、goコードから何を呼び出すかを正確に決定する必要があります。 1つの文字列パラメーターを持つ関数とします。
 extern { fn HelloFromGo(name: *const libc::c_char); } 

次に、接続してgoを呼び出すことができる関数を宣言する必要があります。 #[no_mangle]extern "C"注意してください。 1つ目はrust-yに、コンパイルプロセス中にファイルの名前をあらゆる方法で変更してはならないことを伝え、2つ目は、ファイルとしてファイルをエクスポートすることを伝えます。
 #[no_mangle] pub extern "C" fn hello_from_rust(name: *const libc::c_char) { let buf_name = unsafe { CStr::from_ptr(name).to_bytes() }; let str_name = String::from_utf8(buf_name.to_vec()).unwrap(); println!("go\t: {}", str_name); 

go関数をもう少し呼び出します。
  let hello = CString::new(" :3 ,  Nim  ?").unwrap(); unsafe { HelloFromGo(hello.as_ptr()); } } 


キューに行く


ここで、 hello_from_rustを呼び出し、main関数を含むコードを作成する必要があります。

mainというパッケージを宣言し、出力ライブラリをインポートします。
 package main import "fmt" 

さて、さびで書いたものをすべてインポートする必要があります。 アセンブリユーティリティが呼び出されると、goはリンカーも呼び出します。 rustで書かれたリリースバージョンのライブラリがあることに同意します。 また、静的ライブラリがあるため、 mdlもインポートする必要があります。
 /* #cgo LDFLAGS: -L./target/release -lhello -lm -ldl void hello_from_rust(char *name); */ import "C" 

次に、rustから呼び出される関数を作成する必要があります。 fの前のコメントは、goコンパイラーにインポートするように指示します。
 //export HelloFromGo func HelloFromGo(name *C.char) { fmt.Println("rust\t:", C.GoString(name)) } 

アプリケーションへのエントリポイントを書き込むためだけに残ります。 go外部のhello_from_rust関数がhello_from_rusthello_from_rust
 func main() { C.hello_from_rust(C.CString(" Rust!")) } 


おわりに


以上です。 これで、友好的な結合をMakefileに統合することになります。
 build: cargo build --release go build main.go clean: cargo clean rm -f "./main" 

安全にコンパイルして実行できます。 コードはここで取得できます

:wq

Source: https://habr.com/ru/post/J262889/


All Articles