简体   繁体   English

如何从 Rust 调用原始地址?

[英]How can I call a raw address from Rust?

I am writing an OS in Rust and need to directly call into a virtual address that I'm calculating (of type u32 ).我正在用 Rust 编写操作系统,需要直接调用我正在计算的虚拟地址(类型u32 )。 I expected this to be relatively simple:我希望这相对简单:

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

However, this complains that the cast is non-primitive.然而,这抱怨演员是非原始的。 It suggests I use the From trait, but I don't see how this could help (although I am relatively new to Rust and so could be missing something).它建议我使用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

I have everything in libcore at my disposal, but haven't ported std and so can't rely on anything that isn't no_std我可以使用libcore中的所有内容,但尚未移植std ,因此不能依赖任何不是 no_std 的内容

Casts of the type _ as f-ptr are not allowed (see the Rustonomicon chapter on casts ).不允许将_ as f-ptr类型转换_ as f-ptr (请参阅有关 casts 的 Rustonomicon 章节)。 So, as far as I can tell, the only way to cast to function pointer types is to use the all mighty weapon mem::transmute() .因此,据我所知,转换为函数指针类型的唯一方法是使用强大的武器mem::transmute()

But before we can use transmute() , we have to bring our input into the right memory layout.但是在我们可以使用transmute() ,我们必须将我们的输入带入正确的内存布局。 We do this by casting to *const () (a void pointer).我们通过强制转换为*const () (一个空指针)来做到这一点。 Afterwards we can use transmute() to get what we want:之后我们可以使用transmute()来获得我们想要的:

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

If you find yourself doing this frequently, various kinds of macros can remove the boilerplate.如果您发现自己经常这样做,各种宏可以删除样板。 One possibility:一种可能:

macro_rules! example {
    ($address:expr, $t:ty) => {
        std::mem::transmute::<*const (), $t>($address as _)
    };
}
let f = unsafe { example!(virtual_address, extern "C" fn()) };
f(); 

However, a few notes on this:但是,对此有几点说明:

  • If you, future reader, want to use this to do simple FFI things: please take a moment to think about it again.如果你,未来的读者,想用它来做简单的 FFI 事情:请花点时间再考虑一下。 Calculating function pointers yourself is rarely necessary.很少需要自己计算函数指针。
  • Usually extern "C" functions have the type unsafe extern "C" fn() .通常extern "C"函数的类型为unsafe extern "C" fn() This means that those functions are unsafe to call.这意味着调用这些函数是不安全的。 You should probably add the unsafe to your function.您可能应该将unsafe添加到您的函数中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM