溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Rust閉包實(shí)例分析

發(fā)布時(shí)間:2022-04-27 11:14:19 來源:億速云 閱讀:233 作者:iii 欄目:大數(shù)據(jù)

這篇“Rust閉包實(shí)例分析”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Rust閉包實(shí)例分析”文章吧。

閉包
我們知道 Rust 的閉包不僅是一個(gè)函數(shù)指針,這意味著不能使用它作為回調(diào)函數(shù)的函數(shù)指針直接傳遞給 C 端。
同時(shí)我們也知道 Rust 中的所有的閉包都實(shí)現(xiàn)了由標(biāo)準(zhǔn)庫提供的 trait    Fn  、  FnMut   或    FnOnce   中的一個(gè)。閉包語法    || {}   實(shí)際上是    Fn   系列 trait 的語法糖,Rust 會(huì)為“環(huán)境”創(chuàng)建一個(gè)結(jié)構(gòu)體,  impl  其中合適的一個(gè) trait,并使用它。
因此,從理論上講,我們應(yīng)該能夠通過將閉包“拆分”為兩部分,匿名類型的實(shí)例數(shù)據(jù)和某種類似  call()  方法的函數(shù)。這樣我們可以獲取其中函數(shù)部分的指針,從而實(shí)現(xiàn)將閉包傳遞給 C 端代碼。
具體的方法就是:首先創(chuàng)建一個(gè)泛型 hook 函數(shù),該函數(shù)和回調(diào)函數(shù)的參數(shù)列表一樣,在其中構(gòu)建并調(diào)用閉包。然后創(chuàng)建一個(gè) getter 函數(shù),該函數(shù)接受閉包的引用作為參數(shù),返回一個(gè)函數(shù)指針。
我們沿用上篇設(shè)計(jì)的示例,稍作修改:
  1. C 端, sum_square_cb  函數(shù),接收兩個(gè)整型參數(shù) a, b,一個(gè)函數(shù)指針,一個(gè) void * ;
  2. Rust 端,定義一個(gè) getter 函數(shù)  get_callback ;
  3. Rust 端,定義一個(gè)閉包,被調(diào)用時(shí)更新數(shù)據(jù) user_data;
  4. Rust 端,調(diào)用 C 中定義的  sum_square_cb
好,代碼部分 C 端保持不變,我們看 Rust 端的兩個(gè)函數(shù)  hook   和  get_callback  ,代碼如下:
  
// ffi/example_10/src/main.rs
unsafe extern fn hook<F>(result: c_int, user_data: *mut c_void)where    F: FnMut(c_int),{    let closure = &mut *(user_data as *mut F);    closure(result);}
pub fn get_callback<F>(_closure: &F) -> SumSquareCBwhere    F: FnMut(c_int),{    hook::<F>}
 
由于我們希望閉包能改變其環(huán)境,所以在定義  hook  函數(shù)時(shí),我們限定閉包實(shí)現(xiàn)為  FnMut  并以  c_int  作為參數(shù)。在函數(shù)體中的這一句    let closure = &mut *(user_data as *mut F);   ,先通過把    *mut c_void   指針轉(zhuǎn)換成    *mut F   指針,然后用    *   取得它的數(shù)據(jù)塊,并使用    &mut   取得可變引用 ,最后調(diào)用閉包。
同時(shí)  get_callback  函數(shù)中僅有的語句,  hook::<F>  ,我們使用了一個(gè)叫做 turbofish     ::<>    的語法,用來顯式指定返回  F  類型的  hook  函數(shù)。
接下來我們 Rust 端的主函數(shù),代碼如下:
  
fn main() {    let mut record = SumRecord::default();        unsafe {        let mut closure = |result: c_int| {            record.total += result;            record.calls += 1;        };        let callback = get_callback(&closure);
       sum_square_cb(1, 2, callback, &mut closure as *mut _ as *mut c_void);
       sum_square_cb(3, 4, callback, &mut closure as *mut _ as *mut c_void);    }
   println!("The sum is {:?}", record);}
 
這個(gè)    let mut closure   語句意味著    closure   包含一個(gè)匿名函數(shù)的 定義,而不是調(diào)用后的 返回值,該函數(shù)接受一個(gè)  c_int  類型的參數(shù)。我們使用閉包的原因是需要事先定義一段代碼,并在之后的某個(gè)時(shí)候才實(shí)際調(diào)用它。這里我們將期望調(diào)用的代碼儲(chǔ)存在了    closure   中。
接著我們調(diào)用  get_callback  ,其中有一點(diǎn)非常重要,它返回的函數(shù)指針只能在傳入的同一閉包上使用。因?yàn)槲覀兌x  hook  函數(shù)時(shí)在未進(jìn)行任何類型檢查的情況下,將  user_data  直接轉(zhuǎn)換為該閉包類型的指針。
同時(shí)在調(diào)用 C 端函數(shù)  sum_square_cb  時(shí),我們通過獲取閉包變量    closure  的可變引用,并進(jìn)行兩次指針轉(zhuǎn)換,將其強(qiáng)制轉(zhuǎn)換為    void *   指針來獲取其數(shù)據(jù)。其中我們使用了  _  占位符由 Rust 編譯器來推斷該位置的閉包類型。

以上就是關(guān)于“Rust閉包實(shí)例分析”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)
推薦閱讀:
  1. Python 閉包
  2. lua 閉包

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI