我如何从 Rust 调用原始地址?
How can I call a raw address from Rust?
我正在用 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). 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()
来得到我们想要的:
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();
但是,对此有几点说明:
- 如果你,未来 reader,想用它来做简单的 FFI 事情:请花点时间再考虑一下。很少需要自己计算函数指针。
- 通常
extern "C"
函数的类型为 unsafe extern "C" fn()
。这意味着调用这些函数是不安全的。您可能应该将 unsafe
添加到您的函数中。
我正在用 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). 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()
来得到我们想要的:
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();
但是,对此有几点说明:
- 如果你,未来 reader,想用它来做简单的 FFI 事情:请花点时间再考虑一下。很少需要自己计算函数指针。
- 通常
extern "C"
函数的类型为unsafe extern "C" fn()
。这意味着调用这些函数是不安全的。您可能应该将unsafe
添加到您的函数中。