从Rust调用一个原始地址

时间:2017-09-09 19:41:51

标签: rust function-pointers osdev

我在Rust中编写操作系统,需要直接调用我正在计算的虚拟地址(类型u32)。我希望这相对简单:

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的内容

1 个答案:

答案 0 :(得分:5)

不允许使用_ as f-ptr类型的强制转型(请参阅the Rustonomicon chapter on casts)。所以,据我所知,转换为函数指针类型的唯一方法是使用所有强大的武器mem::transmute()

但在我们使用transmute()之前,我们必须将输入带入正确的内存布局。我们通过转换为*const ()(一个void指针)来做到这一点。之后我们可以使用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添加到您的函数中。