我正在用 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 的东西
类型的演员表_ as f-ptr
不允许(参见Rustonomicon 关于强制转换的章节 https://doc.rust-lang.org/nomicon/casts.html)。因此,据我所知,转换为函数指针类型的唯一方法是使用万能的武器mem::transmute() https://doc.rust-lang.org/stable/std/mem/fn.transmute.html.
但在我们可以使用之前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();
但是,对此有一些注意事项:
- 如果您,未来的读者,想用它来做简单的 FFI 事情:请花点时间再考虑一下。很少需要自己计算函数指针。
- Usually
extern "C"
函数具有类型unsafe extern "C" fn()
。这意味着调用这些函数是不安全的。你可能应该添加unsafe
到你的函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)