欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go調(diào)用Rust方法及外部函數(shù)接口前置

 更新時間:2022年06月13日 16:22:30   作者:張晉濤  
這篇文章主要為大家介紹了Go調(diào)用Rust方法及外部函數(shù)接口前置示例實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

近期 Rust 社區(qū)/團隊有些變動,所以再一次將 Rust 拉到大多數(shù)人眼前。

我最近看到很多小伙伴說的話:

  • Rust 還值得學(xué)嗎?社區(qū)是不是不穩(wěn)定呀
  • Rust 和 Go 哪個好?
  • Rust 還值得學(xué)嗎?

這些問題如果有人來問我,那我的回答是:

小孩子才做選擇,我都要!

當然,關(guān)于 Rust 和 Go 的問題也不算新,比如之前的一條推文:

我在本篇中就來介紹下如何用 Go 調(diào)用 Rust。

當然,這篇中我基本上不會去比較 Go 和 Rust 的功能,或者這種方式的性能之類的,Just for Fun

FFI 和 Binding

FFI (Foreign Function Interface) 翻譯過來叫做外部函數(shù)接口(為了比較簡單,下文中都將使用 FFI 指代)。最早來自于 Common Lisp 的規(guī)范,這是在 wiki 上寫的,我并沒有去考證。 不過我所使用過的絕大多數(shù)語言中都有 FFI 的概念/術(shù)語存在,比如:Python、Ruby, Haskell、Go、Rust、LuaJIT 等。

FFI 的作用簡單來說就是允許一種語言去調(diào)用另一種語言,有時候我們也會用 Binding 來表示類似的能力。

在不同的語言中會有不同的實現(xiàn),比如在 Go 中的 cgo , Python 中的 ctypes , Haskell 中的 CAPI (之前還有一個 ccall)等。 我個人感覺 Haskell 中用 FFI 相比其他語言要更簡單&方便的多,不過這不是本篇的重點就不展開了。

在本文中,對于 Go 和 Rust 而言,它們的 FFI 需要與 C 語言對象進行通信,而這部分其實是由操作系統(tǒng)根據(jù) API 中的調(diào)用約定來完成的。

我們來進入正題。

準備 Rust 示例程序

Rust 的安裝和 Cargo 工具的基本使用,這里就不介紹了。大家可以去 Rust 的官網(wǎng)進行了解。

用 Cargo 創(chuàng)建項目

我們先準備一個目錄用來放本次示例的代碼。(我創(chuàng)建的目錄叫做 go-rust )

然后使用 Rust 的 Cargo 工具創(chuàng)建一個名叫 rustdemo 的項目,這里由于我增加了 --lib 的選項,使用其內(nèi)置的 library 模板。

?  go-rust git:(master) ? mkdir lib && cd lib
?  go-rust git:(master) ? cargo new --lib rustdemo
     Created library `rustdemo` package
?  go-rust git:(master) ? tree rustdemo 
rustdemo
├── Cargo.toml
└── src
    └── lib.rs
1 directory, 2 files

準備 Rust 代碼

extern crate libc;
use std::ffi::{CStr, CString};
#[no_mangle] 
pub extern "C" fn rustdemo(name: *const libc::c_char) -> *const libc::c_char {
    let cstr_name = unsafe { CStr::from_ptr(name) };
    let mut str_name = cstr_name.to_str().unwrap().to_string();
    println!("Rust get Input:  \"{}\"", str_name);
    let r_string: &str = " Rust say: Hello Go ";
    str_name.push_str(r_string);
    CString::new(str_name).unwrap().into_raw()
}

代碼比較簡單,Rust 暴露出來的函數(shù)名叫做 rustdemo ,接收一個外部的參數(shù),并將其打印出來。之后從 Rust 這邊再設(shè)置一個字符串。

CString::new(str_name).unwrap().into_raw() 被轉(zhuǎn)換為原始指針,以便之后由 C 語言處理。

編譯 Rust 代碼

我們需要修改下 Cargo.toml 文件以便進行編譯。注意,這里我們增加了 crate-type = ["cdylib"] 和 libc 。

[package]
name = "rustdemo"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
libc = "0.2"

然后進行編譯

?  rustdemo git:(master) ? cargo build --release
   Compiling rustdemo v0.1.0 (/home/tao/go/src/github.com/tao12345666333/go-rust/lib/rustdemo)
    Finished release [optimized] target(s) in 0.22s

查看生成的文件,這是一個 .so 文件(這是因為我在 Linux 環(huán)境下,你如果在其他系統(tǒng)環(huán)境下會不同)

?  rustdemo git:(master) ? ls target/release/librustdemo.so 
target/release/librustdemo.so

準備 Go 代碼

Go 環(huán)境的安裝之類的這里也不再贅述了,繼續(xù)在我們的 go-rust 目錄操作即可。

編寫 main.go

package main
/*
#cgo LDFLAGS: -L./lib -lrustdemo
#include <stdlib.h>
#include "./lib/rustdemo.h"
*/
import "C"
import (
	"fmt"
	"unsafe"
)
func main() {
	s := "Go say: Hello Rust"
	input := C.CString(s)
	defer C.free(unsafe.Pointer(input))
	o := C.rustdemo(input)
	output := C.GoString(o)
	fmt.Printf("%s\n", output)
}

在這里我們使用了 cgo ,在 import "C" 之前的注釋內(nèi)容是一種特殊的語法,這里是正常的 C 代碼,其中需要聲明使用到的頭文件之類的。

下面的代碼很簡單,定義了一個字符串,傳遞給 rustdemo 函數(shù),然后打印 C 處理后的字符串。

同時,為了能夠讓 Go 程序能正常調(diào)用 Rust 函數(shù),這里我們還需要聲明其頭文件,在 lib/rustdemo.h 中寫入如下內(nèi)容:

char* rustdemo(char *name);

編譯代碼

在 Go 編譯的時候,我們需要開啟 CGO (默認都是開啟的),同時需要鏈接到 Rust 構(gòu)建出來的 rustdemo.so 文件,所以我們將該文件和它的頭文件放到 lib 目錄下。

?  go-rust git:(master) ? cp lib/rustdemo/target/release/librustdemo.so lib

所以完整的目錄結(jié)構(gòu)就是:

?  go-rust git:(master) ? tree -L 2 .
.
├── go.mod
├── lib
│   ├── librustdemo.so
│   ├── rustdemo
│   └── rustdemo.h
└── main.go
2 directories, 5 files

編譯:

?  go-rust git:(master) ? go build -o go-rust  -ldflags="-r ./lib" main.go
?  go-rust git:(master) ? ./go-rust 
Rust get Input:  "Go say: Hello Rust"
Go say: Hello Rust Rust say: Hello Go

可以看到,第一行的輸出是由 Go 傳入了 Rust , 第二行中則是從 Rust 再傳回 Go 的了。符合我們的預(yù)期。

總結(jié)

本篇介紹了如何使用 Go 與 Rust 進行結(jié)合,介紹了其前置關(guān)于 FFI 相關(guān)的知識,后續(xù)通過一個小的實踐演示了其完整過程。 感興趣的小伙伴可以自行實踐下,更多關(guān)于Go調(diào)用Rust外部函數(shù)接口前置的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入了解Rust中trait的使用

    深入了解Rust中trait的使用

    先前我們提到過?trait,那么Rust中的trait?是啥呢?本文將通過一些示例為大家詳細講講Rust中trait的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • C++的替代:微軟如何使用rust?

    C++的替代:微軟如何使用rust?

    這篇文章主要介紹了微軟如何使用rust的,幫助大家了解c++和rust這兩門編程語言的聯(lián)系與區(qū)別,感興趣的朋友可以了解下
    2020-09-09
  • 關(guān)于rust的模塊引入問題

    關(guān)于rust的模塊引入問題

    Rust 語言是一種高效、可靠的通用高級語言,它的執(zhí)行效率也是令人稱贊的,是一種少有的兼顧開發(fā)效率和執(zhí)行效率的語言,這篇文章主要介紹了rust的模塊引入相關(guān)知識,需要的朋友可以參考下
    2022-10-10
  • Rust使用Channel實現(xiàn)跨線程傳遞數(shù)據(jù)

    Rust使用Channel實現(xiàn)跨線程傳遞數(shù)據(jù)

    消息傳遞是一種很流行且能保證安全并發(fā)的技術(shù),Rust也提供了一種基于消息傳遞的并發(fā)方式,在rust里使用標準庫提供的Channel來實現(xiàn),下面我們就來學(xué)習(xí)一下如何使用Channel實現(xiàn)跨線程傳遞數(shù)據(jù)吧
    2023-12-12
  • Rust?連接?PostgreSQL?數(shù)據(jù)庫的詳細過程

    Rust?連接?PostgreSQL?數(shù)據(jù)庫的詳細過程

    這篇文章主要介紹了Rust?連接?PostgreSQL?數(shù)據(jù)庫的完整代碼,本文圖文實例代碼相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • rust流程控制的具體使用

    rust流程控制的具體使用

    在Rust中,控制流包括條件語句、循環(huán)和匹配模式等,用于實現(xiàn)程序的邏輯和流程控制,本文就來詳細的介紹一下,感興趣的可以了解一下
    2023-12-12
  • Rust中FFI編程知識點整理總結(jié)(推薦)

    Rust中FFI編程知識點整理總結(jié)(推薦)

    這篇文章主要介紹了Rust中FFI編程知識點整理總結(jié),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 詳解Rust Substrate框架中的Runtime

    詳解Rust Substrate框架中的Runtime

    ubstrate是一個區(qū)塊鏈開發(fā)框架,它提供了一系列模塊化和可擴展的組件,可以幫助開發(fā)人員快速構(gòu)建自定義區(qū)塊鏈。 Runtime是Substrate區(qū)塊鏈的核心部分,文中有詳細的代碼示例,需要的朋友可以參考下
    2023-05-05
  • C和Java沒那么香了,Serverless時代Rust即將稱王?

    C和Java沒那么香了,Serverless時代Rust即將稱王?

    Serverless Computing,即”無服務(wù)器計算”,其實這一概念在剛剛提出的時候并沒有獲得太多的關(guān)注,直到2014年AWS Lambda這一里程碑式的產(chǎn)品出現(xiàn)。Serverless算是正式走進了云計算的舞臺
    2021-06-06
  • 詳解Rust語言中anyhow的使用

    詳解Rust語言中anyhow的使用

    anyhow是一個Rust庫,用于簡化錯誤處理和提供更好的錯誤報告,這個庫適合用于應(yīng)用程序,而不是用于創(chuàng)建庫,因為它提供了一個非結(jié)構(gòu)化的,方便使用的錯誤類型,本文就給大家講講Rust語言中anyhow的使用,需要的朋友可以參考下
    2023-08-08

最新評論