如何从Rust调用原始地址? [英] How can I call a raw address from Rust?

查看:93
本文介绍了如何从Rust调用原始地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing an OS in Rust and need to directly call into a virtual address that I'm calculating (of type u32). I expected this to be relatively simple:

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

但是,这抱怨演员表不是原始的.这表明我使用了 From 特性,但是我看不出它有什么帮助(尽管我对Rust还是比较陌生,所以可能会遗漏一些东西).

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).

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

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

推荐答案

_类型为f-ptr 的类型的广播(请参见

Casts of the type _ as f-ptr are not allowed (see the Rustonomicon chapter on casts). 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().

但是在使用 transmute()之前,我们必须将输入内容放入正确的内存布局中.我们通过强制转换为 * const()(一个无效指针)来实现.然后,我们可以使用 transmute()来获得我们想要的东西:

But before we can use transmute(), we have to bring our input into the right memory layout. We do this by casting to *const () (a void pointer). Afterwards we can use transmute() to get what we want:

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:

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

这篇关于如何从Rust调用原始地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆