2017-09-09 192 views
1

我正在Rust中編寫一個操作系統,需要直接調用我計算的虛擬地址(類型爲u32)。我認爲這是相對簡單的:從Rust調用一個原始地址

let code = virtual_address as (extern "C" fn()); 
(code)(); 

但是,這抱怨演員是非原始的。這表明我使用了From特質,但我不明白這可能會有什麼幫助(雖然我對Rust比較新,所以可能會漏掉一些東西)。

error[E0605]: non-primitive cast: `u32` as `extern "C" fn()` 
--> src/main.rs:3:16 
    | 
3 |  let code = virtual_address as (extern "C" fn()); 
    |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    | 
    = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait 

注:我在libcore一切都在我手上,但還沒有移植std,所以不能依靠任何不no_std類型_ as f-ptr

回答

3

強制類型轉換是不允許(見the Rustonomicon chapter on casts)。所以,據我所知,轉換爲函數指針類型的唯一方法是使用所有強大的武器mem::transmute()

但是在我們可以使用transmute()之前,我們必須將我們的輸入帶入正確的內存佈局。我們通過投射到*const()(一個空指針)來做到這一點。以後我們就可以使用transmute()得到我們想要的:

let ptr = virtual_address as *const(); 
let code: extern "C" fn() = unsafe { std::mem::transmute(ptr) }; 
(code)(); 

然而,幾個音符在此:

  • 如果,未來的讀者,想用這個做簡單的FFI的事情:請花一點時間再考慮一下。很少需要自己計算函數指針。
  • 通常extern "C"函數的類型爲unsafe extern "C" fn()。這意味着這些功能是不安全的。您應該添加unsafe到您的功能。
+0

請注意,我絕對不是不安全事物的專家!如果有人知道更好,請讓我知道;那麼我可以編輯或刪除我的答案! –

+0

Rust在這裏沒有做任何事情。 'fn()'是一個普通的函數指針。只要'virtual_address'處有一個函數,調用約定和簽名匹配,就可以執行轉換並調用函數。 – red75prime

+0

真棒,我需要做一些更多的設置,看看這是否真的有效,但它確實編譯!非常感謝@LukasKalbertodt。 –

相關問題