rust - 如何从Rust调用原始地址?

标签 rust function-pointers osdev

我正在Rust中编写一个OS,需要直接调用我正在计算的虚拟地址(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的东西。

最佳答案

不允许类型为_ as f-ptr的强制类型转换(请参阅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)();
如果您发现自己经常这样做,则各种宏都可以删除样板。一种可能性:
macro_rules! example {
    ($address:expr, $t:ty) => {
        std::mem::transmute::<*const (), $t>($address as _)
    };
}
let f = unsafe { example!(virtual_address, extern "C" fn()) };
f(); 

但是,关于此的一些注意事项:
  • ,如果您是 future 的读者,想使用此功能来完成简单的FFI事情:请花点时间再考虑一下。很少自己计算函数指针。
  • 通常,extern "C"函数的类型为unsafe extern "C" fn()。这意味着这些函数是不安全的。您可能应该将unsafe添加到您的函数中。
  • 关于rust - 如何从Rust调用原始地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65583966/

    相关文章:

    regex - 在 Rust 中连接两个正则表达式字符串

    c++ - 如何调用这个函数指针

    c++ - 如何使指针指向非成员函数?

    c - 启用分页时 QEMU 三重故障

    json - 根据 JSON 中的字段有条件地解码 JSON

    rust - 如何使用 Serde 的自定义(反)序列化来更新任意输入的子集?

    syntax - rust 编译器 "error: can' t 捕获 fn 项中的动态环境是什么;使用|| { ... } closure form instead"的意思,如何解决呢?

    c++ - Boost.Fusion 功能 : Calling functions with default arguments

    c - 如何在 C 中正确创建内核并链接到引导加载程序

    assembly - Qemu 和原始二进制文件