Zu einer Zeit gab es einen Artikel über Habr darüber, wie man Rust-Code von Go aus aufruft . Der Artikel ist nicht schlecht, aber schwer zu verstehen und wehrt Anfänger tatsächlich von dem Wunsch ab, auf beide Sprachen zu schauen. Der Zweck dieses Beitrags besteht nicht darin, sprachübergreifende Anrufe zu vertiefen, sondern zu zeigen, wie einfach dies möglich ist.
Wir werden nicht weit gehen und ein Beispiel aus einem Buch über das Erlernen der Rust-Sprache nehmen.In diesem Beispiel werden lediglich 10 Threads gestartet, in denen die Variable 'x' auf 5 Millionen erhöht wird und eine Meldung zum Ende des Streams angezeigt wird.use std::thread;
#[no_mangle]
pub extern "C" fn process() {
let handles:Vec<_> = (0..10).map(|_|{
thread::spawn(||{
let mut x = 0;
for _ in 0..5_000_000 {
x += 1
}
x
})
}).collect();
for h in handles {
println!("Thread finished with count={}",
h.join().map_err(|_| "Could not join thread!").unwrap());
}
println!("Done!");
}
Sie müssen die Frachtdatei auch bearbeiten, indem Sie eine Zeile hinzufügenKistentyp = ["cdylib"]
Als Ergebnis wird eine Bibliothek mit der Möglichkeit erstellt, Funktionen über die Foreign Function Interface (FFI) aufzurufen .Es ist erwähnenswert, dass libembed.dylib eine Bibliothek unter Mac OS ist, unter Linux libembed.so und unter Windows libembed.dll.
Vielen Dank: bingo347
Cargo.toml[package]
name = "embed"
version = "0.1.0"
[lib]
crate-type = ["cdylib"]
Im Allgemeinen ist dies alles, was Sie in der Rust-Bibliothek tun müssen. Ein Beispiel aus dem Buch beschreibt dies ausführlicher und wir werden nicht weiter darauf eingehen.Wir kompilieren die Bibliothek mit dem Befehl:Frachtbau - Release
Jetzt ist es unser Ziel, diesen Code aus der Go-Anwendung aufzurufen. Wir erstellen eine einfache Anwendung und fügen in unserem Projekt den lib-Ordner hinzu, in den wir die Datei /target/release/libembed.dylib kopieren . Im Inneren erstellen wir eine Datei mit dem Namen der Funktion und beschreiben deren Aufrufsignatur.lib / process.hvoid process();
In der Go-Datei fügen wir solche Anweisungen hinzu und unsere main.go wird so aussehenpackage main
import "C"
func main() {
C.process()
}
Das Projekt zusammenstellengo build -ldflags = "- r / lib" main.go
Achten Sie auf den Parameter ldflags. In diesem Fall legen wir lediglich den Pfad zum dynamischen ELF-Linker fest.Alle. Führen Sie das Programm aus und erhalten Sie die Ausgabe.
Erwähnenswert ist auch, dass Sie die Lehren aus dem Go-Programm in die Rust-Bibliothek übertragen können. Dazu transformieren wir die Funktion in der Rust-Bibliothek so, dass sie einen Zeichenfolgenwert annimmt.extern crate libc;
use std::thread;
use std::ffi::CStr;
#[no_mangle]
pub extern "C" fn process(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();
let handles:Vec<_> = (0..10).map(|_|{
thread::spawn(||{
let mut x = 0;
for _ in 0..5_000_000 {
x += 1
}
x
})
}).collect();
for h in handles {
println!("{}:Thread finished with count={}\n",
str_name,
h.join().map_err(|_| "Could not join thread!\n").unwrap());
}
println!("Done!");
}
Wir stellen unser Projekt zusammen, kopieren die Bibliothek erneut in den Ordner lib und ändern die Datei process.h auf diese Weisevoid process (char * name);
Wir übergeben die Zeile aus der Go-Anwendung (in unserem Fall: „Hallo aus Golang“) .package main
import "C"
func main() {
C.process(C.CString("Hello from Golang !!"))
}
Alle. Führen Sie das Programm aus und erhalten Sie die Ausgabe.