Ao mesmo tempo, havia um artigo sobre Habr sobre como chamar o código Rust da Go . O artigo não é ruim, mas difícil de entender e realmente repele os iniciantes do desejo de olhar para os dois idiomas. O objetivo deste post não é muito para entrar nas entranhas das chamadas em vários idiomas, mas mostrar como é fácil fazer isso.
Não iremos longe e daremos um exemplo de um livro sobre o aprendizado da linguagem Rust.Tudo o que este exemplo faz é iniciar 10 threads, nos quais incrementa a variável 'x' para 5 milhões e exibe uma mensagem sobre o final do fluxo.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!");
}
Você também precisa editar o arquivo de carga adicionando uma linha a eletipo de caixa = ["cdylib"]
Como resultado, será criada uma biblioteca com a capacidade de chamar funções por meio da Foreign Function Interface (FFI) .Vale ressaltar que libembed.dylib é uma biblioteca no Mac OS, no Linux será libembed.so e no Windows será libembed.dll
Obrigado: bingo347
Cargo.toml[package]
name = "embed"
version = "0.1.0"
[lib]
crate-type = ["cdylib"]
Em geral, isso é tudo o que você precisa fazer na biblioteca Rust. Um exemplo do livro descreve isso com mais detalhes e não vamos nos deter sobre isso.Nós compilamos a biblioteca com o comando:construção de carga - liberação
Agora, nosso objetivo é chamar esse código do aplicativo Go. Criamos um aplicativo simples e, dentro do nosso projeto, adicionamos a pasta lib na qual copiamos o arquivo /target/release/libembed.dylib . Dentro, criamos um arquivo com o nome da função e descrevemos sua assinatura de chamada.lib / process.hvoid process();
Dentro do arquivo Go, adicionamos essas diretivas e nosso main.go ficará assimpackage main
import "C"
func main() {
C.process()
}
Montando o projetová construir -ldflags = "- r / lib" main.go
Preste atenção ao parâmetro ldflags, neste caso, tudo o que fazemos é definir o caminho para o vinculador dinâmico ELF.Todos. Execute o programa e obtenha a saída.
Também é importante mencionar separadamente que você pode transferir os ensinamentos do programa Go para a biblioteca Rust. Para fazer isso, transformamos a função na biblioteca Rust para que ela use um valor de string.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!");
}
Montamos nosso projeto, copiamos a biblioteca para a pasta lib novamente, modificamos o arquivo process.h dessa maneiraprocesso nulo (char * name);
Passamos a linha do aplicativo Go (no nosso caso: "Hello from Golang") .package main
import "C"
func main() {
C.process(C.CString("Hello from Golang !!"))
}
Todos. Execute o programa e obtenha a saída.