最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2022年09月14日 16:47:52   作者:小魚編程  
這篇文章主要介紹了Rust中FFI編程知識點整理總結(jié),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

Rust語言對FFI的支持

Rust 語言主要在關(guān)鍵字和標(biāo)準(zhǔn)庫兩個方面對 FFI 提供了支持,具體如下:
關(guān)鍵字 extern
屬性 #[no_mangle]
外部塊 ExternBlock 及其屬性 link 和 link_name
標(biāo)準(zhǔn)庫
std:os:raw 模塊:例如c_char。
std:ffi 模塊:傳遞 UTF-8 字符串時,CString和CStr很有用。

libc-crate庫

你可以使用 libc::foo 這種形式訪問這個庫中的任何導(dǎo)出內(nèi)容。
在Rust里,只能創(chuàng)建子線程,如果想創(chuàng)建子進程,就需要用到libc庫

fn main() {    
unsafe {        
let pid = libc::fork();                                                                                                               if pid > 0 {println!("Hello, I am parent thread: {}", libc::getpid());}   
else if pid == 0 {println!("Hello, I am child thread: {}", libc::getpid());println!("My parent thread: {}", libc::getppid());        }        
else {println!("Fork creation failed!");}}}

1.libc 的所有函數(shù)調(diào)用,都必須放進 unsafe 塊中。因為它的所有調(diào)用都是 unsafe 的;
2.std 的線程操作封裝,好用,形象。libc 的進程操作,與 C 語言系統(tǒng)編程一樣,完全是另外一套思路和編程風(fēng)格;
3.std 的線程操作雖然簡潔,但是也缺少更細顆粒度的控制。而 libc 可以對進程的操作(及后面對子進程的功能擴充,父進程中的信號管理等),做到完全的控制,更加靈活,功能強大;
4.std 本身無法實現(xiàn)進程 fork 的功能。
因為我 Rust 的封裝是 zero cost (零成本)的。零成本抽象賦予了 Rust 系統(tǒng)編程的能力。

libc 與 std::os:??::raw,這里面有的用法是一樣的,沒有任何問題。簡單的和C交互可以用os:raw里面的,而一旦產(chǎn)生了系統(tǒng)調(diào)用或者 Unix 環(huán)境編程,那么就得引入 libc 庫來操作。

cbindgen 工具的介紹和使用

這個工具就是將寫好的Rust代碼配置一下,然后會自動生成接口代碼頭文件等等。其實,F(xiàn)FI封裝、轉(zhuǎn)換,熟悉了之后,知識點就那些,模式也比較固定,如果接口量很大,那就需要大量重復(fù)的 coding。量一大,人手動綁定出錯的機率也大。所以這種輔助工具的意義就顯露出來了?;谳o助工具生成的代碼,如不完美,再適當(dāng)手動修一修,幾下就能搞定,大大提高生產(chǎn)效率。

Rust指針

在Rust中,存在三種類型的指針:

1.Rust自帶的指針類型:

引用—安全的指針

&T:它是對類型T的不可變引用
&mut T:它是對類型T的可變引用

2. 原始指針

眾所周知,Rust語言的指針是一種安全的指針,它會遵循一定的規(guī)則,比如ownership規(guī)則,會確保不出現(xiàn)懸掛指針。但是當(dāng)我們需要寫一些底層框架的時候,往往需要繞過這些規(guī)則,自由的控制指針,這時候我們就可以使用原始指針。
*const T:表示指向類型T的不可變原始指針。它是Copy類型。這類似于&T,只是它可以為空值。
*mut T:一個指向T的可變原始指針,它不支持Copy特征(non-Copy)。
以下可以定義Rust的原始指針:

fn main() {
    let mut num = 5;
    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;
}

3.智能指針

管理原始指針非常不安全,開發(fā)者在使用它們時需要注意很多細節(jié)。不恰當(dāng)?shù)厥褂盟鼈兛赡軙苑浅k[蔽的方式導(dǎo)致諸如內(nèi)存泄漏、引用掛起,以及大型代碼庫中的雙重釋放等問題。為了解決這些問題,我們可以使用C++中廣泛采用的智能指針。
智能指針的兩個特性:Drop和Deref
Drop:這是多次提及的特征,它可以自動釋放相關(guān)值超出作用域后占用的資源。Drop特征類似于你在其他語言中遇到的被稱為對象析構(gòu)函數(shù)的東西。它包含一個drop方法,當(dāng)對象超出作用域時就會被調(diào)用。該方法將&mut self作為參數(shù)。使用drop釋放值是以LIFO的方式進行的。也就是說,無論最后構(gòu)建的是什么,都首先會被銷毀。drop方法是你為自己的結(jié)構(gòu)體放置清理代碼的理想場所。例如使用引用計數(shù)值或GC時,它尤其方便。當(dāng)我們實例化任何Drop實現(xiàn)值時(任意堆分配類型),Rust編譯器會在編譯后的代碼中每個作用域結(jié)束的位置插入drop方法調(diào)用。因此,我們不需要在這些實例上手動調(diào)用drop方法。
Deref:為了提供與普通指針類似的行為,也就是說,為了能夠解引用被指向類型的調(diào)用方法,智能指針類型通常會實現(xiàn)Deref特征,這允許用戶對這些類型使用解引用運算符*。雖然Deref只為你提供了只讀權(quán)限,但是還有DerefMut,它可以為你提供對底層類型的可變引用。

智能指針的種類:
標(biāo)準(zhǔn)庫中的智能指針有如下幾種。
Box:它提供了最簡單的堆資源分配方式。Box類型擁有其中的值,并且可用于保存結(jié)構(gòu)體中的值,或者從函數(shù)返回它們。
Rc:它用于引用計數(shù)。每當(dāng)獲取新引用時,計數(shù)器會執(zhí)行遞增操作,并在用戶釋放引用時對計數(shù)器執(zhí)行遞減操作。當(dāng)計數(shù)器的值為零時,該值將被移除。
Arc:它用于原子引用計數(shù)。這與之前的類型類似,但具有原子性以保證多線程的安全性。
Cell:它為我們提供實現(xiàn)了Copy特征的類型的內(nèi)部可變性。換句話說,我們有可能獲得多個可變引用。
RefCell:它為我們提供了類型的內(nèi)部可變性,并且不需要實現(xiàn)Copy特征。它用于運行時的鎖定以確保安全性。

引用計數(shù)指針:
所有權(quán)規(guī)則只允許某個給定作用域中存在一個所有者。但是,在某些情況下你需要與多個變量共享類型。例如在GUI庫中,每個子窗體小部件都需要具有對其父容器窗口小部件的引用,以便基于用戶的resize事件來調(diào)整子窗口的布局。雖然有時生命周期允許你將父節(jié)點存儲為&'a Parent,但是它通常受到’a值生命周期的限制,一旦作用域結(jié)束,你的引用將失效。在這種情況下,我們需要更靈活的方法,并且需要使用引用計數(shù)類型。程序中的這些智能指針類型會提供值的共享所有權(quán)。

引用計數(shù)類型支持某個粒度級別的垃圾回收。在這種方法中,智能指針類型允許用戶對包裝值進行多次引用。在內(nèi)部,智能指針使用引用計數(shù)器(這里是refcount)來統(tǒng)計已發(fā)放的并且活動的引用數(shù)量,不過它只是一個整數(shù)值。當(dāng)引用包裝的智能指針值的變量超出作用域時,refcount的值就會遞減。一旦該對象的所有引用都消失,refcount的值也會變成0,之后該值會被銷毀。這就是引用計數(shù)指針的常見工作模式。

Rust為我們提供了兩種引用計數(shù)指針類型。
Rc:這主要用于單線程環(huán)境。
Arc:這主要用于多線程環(huán)境。

Rust和C交互時的各種指針變換

1.pub extern “C” fn sum_of_array(array: *const u32, len: usize) -> u32
slice::from_raw_parts(array,len)
C端傳來的數(shù)組(指針類型),進到Rust這邊進行強制類型轉(zhuǎn)換,變成非可變原始指針類型。函數(shù)slice::from_raw_parts(array,len)就是對原始指針進行轉(zhuǎn)換為Rust切片類型,切片就是一個指針+一個長度即可。

2.CStr::from_ptr(raw_string):CStr就是C端產(chǎn)生數(shù)據(jù),Rust端使用,
只是借用,常用于打印。raw_string是直接從C接過來的可變原始指針。
使用std::ffi::CStr提供的from_ptr方法包裝 C 的字符串指針,它基于空字符’\0’來計算字符串的長度,并可以通過它將外部 C 字符串轉(zhuǎn)換為 Rust 的 &str和String

use std::ffi::CStr;
use libc::c_char;
extern {
fn char_func() -> *mut c_char;
}

fn get_string() -> String {
unsafe {
let raw_string: *mut c_char = char_func();
let cstr = CStr::from_ptr(raw_string);
cstr.to_string_lossy().into_owned()
}
}

3.CStr::from_ptr(s).to_string_lossy().into_owned():注意to_string_lossy()的使用:因為在rust中一切字符都是采用utf8表示的而c不是,
因此如果要將c的字符串轉(zhuǎn)換到rust字符串的話,需要檢查是否都為有效utf-8字節(jié)。

4.CString::new(“Hello, world!”).as_ptr():Cstring是Rust端產(chǎn)生數(shù)據(jù),C端進行使用。
as_ptr()就是將RustCString指針類型轉(zhuǎn)化為C的原始指針類型。

5.CString::new(“Hello world!”).into_raw()
使用std::ffi::CString提供的一對方法into_raw和from_raw可以進行原始指針轉(zhuǎn)換,由于將字符串的所有權(quán)轉(zhuǎn)移給了調(diào)用者,所以調(diào)用者必須將字符串返回給 Rust,以便正確地釋放內(nèi)存。
into_raw()和.as_ptr()的作用類似,都是變成原始指針傳給C端。
6.CString::from_raw(s)
一般在釋放內(nèi)存的時候使用,C端用完需要Rust端來釋放。

7.Box::into_raw(Box::new(new_stu)):其實這里是智能指針和兩端堆棧申請有關(guān),into_raw()就是將Rust智能指針變成原始指針。
8.Box::from_raw(p_stu):from_raw():就是將C端傳來的p_stu變成Rust智能指針。

數(shù)組類型傳遞

C代碼:

  uint32_t sum = sum_of_array(numbers, length);

Rust代碼:

pub extern "C" fn sum_of_array(array: *const u32, len: usize) -> u32 {
    let array = unsafe {
        assert!(!array.is_null());
        slice::from_raw_parts(array, len)
    };
   array.iter().sum()
}

這里的參數(shù)傳遞一目了然,array一開始是C過來的指針類型,通過slice::from_raw_parts(array,len)之后,變成一個Rust切片類型,后面用iter進行求和。切片類型就是一個指針和一組數(shù)據(jù)合在一起組成。

字符串類型

對于C語言來說,字符串有兩種,一種是共享的只讀字符串 char * ,不能修改。另一種是動態(tài)分配的可變字符串 char [],可以修改。
而在Rust里面,字符串是由字符的 UTF-8 編碼組成的字節(jié)序列。表示的類型有很多種。
字符串則比較復(fù)雜,Rust 中的字符串,是一組u8組成的 UTF-8 編碼的字節(jié)序列,字符串內(nèi)部允許NULL字節(jié);但在 C 中,字符串只是指向一個char的指針,用一個NULL字節(jié)作為終止。
我們需要做一些特殊的轉(zhuǎn)換,在 Rust FFI 中使用std::ffi::CStr,它表示一個NULL字節(jié)作為終止的字節(jié)數(shù)組,可以通過 UTF-8 驗證轉(zhuǎn)換成 Rust 中的&str。
CStr:表示以空字符終止的 C 字符串或字節(jié)數(shù)組的借用,屬于引用類型。一般用于和 C 語言交互,由 C 分配并被 Rust 借用的字符串。
CString:表示擁有所有權(quán)的,中間沒有空字節(jié),以空字符終止的字符串類型。一般用于和 C 語言交互時,由 Rust 分配并傳遞給 C 的字符串。
下面這段代碼,在這里get_string使用CStr::from_ptr從C的char*獲取一個字符串,并且轉(zhuǎn)化成了一個String。

fn get_string() -> String {
unsafe {
let raw_string: *mut c_char = char_func();
let cstr = CStr::from_ptr(raw_string);
cstr.to_string_lossy().into_owned()
}
}

和CStr表示從C中來,rust不擁有歸屬權(quán)的字符串相反,CString表示由rust分配,Rust擁有所有權(quán),可以進行修改,用以傳給C程序的字符串。

use std::ffi::CString;
use std::os::raw::c_char;
extern {
fn my_printer(s: *const c_char);
}

let c_to_print = CString::new("Hello, world!").unwrap();
unsafe {
my_printer(c_to_print.as_ptr()); // 使用 as_ptr 將CString轉(zhuǎn)化成char指針傳給c函數(shù)
}

兩端分配堆棧,另一端填充打印

到此這篇關(guān)于Rust中FFI編程知識點整理總結(jié)的文章就介紹到這了,更多相關(guān)Rust中FFI編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文詳解Rust中的錯誤處理

    一文詳解Rust中的錯誤處理

    這篇文章主要為大家詳細介紹了Rust中的錯誤處理的相關(guān)知識,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • Rust指南枚舉類與模式匹配詳解

    Rust指南枚舉類與模式匹配詳解

    這篇文章主要介紹了Rust指南枚舉類與模式匹配精講,枚舉允許我們列舉所有可能的值來定義一個類型,枚舉中的值也叫變體,今天通過一個例子給大家詳細講解,需要的朋友可以參考下
    2022-09-09
  • Rust 模式匹配示例詳解

    Rust 模式匹配示例詳解

    這篇文章主要為大家介紹了Rust 模式匹配示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • 解析rust中的struct

    解析rust中的struct

    自定義的數(shù)據(jù)類型,為相關(guān)聯(lián)的值命名,打包成有意義的組合,類似python的dict,但是賦值的時候可以不按順序,本文給大家介紹下rust中的struct知識,感興趣的朋友一起看看吧
    2022-10-10
  • Rust 中的 Packages 與 Crates模塊化構(gòu)建的基礎(chǔ)及開發(fā)流程

    Rust 中的 Packages 與 Crates模塊化構(gòu)建的基礎(chǔ)及開發(fā)流程

    Rust中的Crate是編譯器處理的最小代碼單元,可以是二進制或庫,每個Crate由一個CrateRoot文件(通常是src/main.rs或src/lib.rs)定義,本文給大家介紹Rust 中的 Packages 與 Crates模塊化構(gòu)建的基礎(chǔ)及開發(fā)流程,感興趣的朋友一起看看吧
    2025-02-02
  • Rust多線程Web服務(wù)器搭建過程

    Rust多線程Web服務(wù)器搭建過程

    這篇文章主要介紹了Rust多線程 Web 服務(wù)器搭建過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • Rust 語言的全鏈路追蹤庫 tracing使用方法

    Rust 語言的全鏈路追蹤庫 tracing使用方法

    這篇文章主要介紹了Rust 語言的全鏈路追蹤庫 tracing,接下來就以 tracing 為例,介紹一下trace 的核心概念以及使用方法,需要的朋友可以參考下
    2022-12-12
  • rust的nutyp驗證和validator驗證數(shù)據(jù)的方法示例詳解

    rust的nutyp驗證和validator驗證數(shù)據(jù)的方法示例詳解

    本文介紹了在Rust語言中,如何使用nuType和validator兩種工具來對Cargo.toml和modules.rs文件進行驗證,通過具體的代碼示例和操作步驟,詳細解釋了驗證過程和相關(guān)配置,幫助讀者更好地理解和掌握使用這兩種驗證工具的方法,更多Rust相關(guān)技術(shù)資訊,可繼續(xù)關(guān)注腳本之家
    2024-09-09
  • Rust?搭建一個小程序運行環(huán)境的方法詳解

    Rust?搭建一個小程序運行環(huán)境的方法詳解

    rust是一門比較新的編程語言,2015年5月15日,Rust編程語言核心團隊正式宣布發(fā)布Rust?1.0版本,本文給大家介紹Rust?搭建一個小程序運行環(huán)境,以iOS?為例介紹開發(fā)環(huán)境的準(zhǔn)備,感興趣的朋友跟隨小編一起看看吧
    2022-05-05
  • Rust的slab庫使用場景分析

    Rust的slab庫使用場景分析

    slab 是一個輕量級、高性能的工具,非常適合管理固定大小的資源集合,尤其是在網(wǎng)絡(luò)編程和事件驅(qū)動架構(gòu)中,這篇文章主要介紹了Rust的slab庫使用教程,需要的朋友可以參考下
    2024-12-12

最新評論

瑞昌市| 东安县| 法库县| 两当县| 蒙阴县| 威远县| 西盟| 宁河县| 竹山县| 广东省| 会同县| 安泽县| 尼勒克县| 右玉县| 甘泉县| 牟定县| 内黄县| 公安县| 密山市| 呼伦贝尔市| 平顶山市| 荔波县| 格尔木市| 潞城市| 兰考县| 衡水市| 虞城县| 卢湾区| 安泽县| 麦盖提县| 开平市| 永德县| 卢龙县| 辉南县| 建平县| 潮安县| 昆明市| 江陵县| 莫力| 班玛县| 九寨沟县|