2017-09-09 95 views
1

我正在Rust中编写一个操作系统,需要直接调用我计算的虚拟地址(类型为u32)。我认为这是相对简单的:从Rust调用一个原始地址

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

回答

3

强制类型转换是不允许(见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)(); 

然而,几个音符在此:

  • 如果,未来的读者,想用这个做简单的FFI的事情:请花一点时间再考虑一下。很少需要自己计算函数指针。
  • 通常extern "C"函数的类型为unsafe extern "C" fn()。这意味着这些功能是不安全的。您应该添加unsafe到您的功能。
+0

请注意,我绝对不是不安全事物的专家!如果有人知道更好,请让我知道;那么我可以编辑或删除我的答案! –

+0

Rust在这里没有做任何事情。 'fn()'是一个普通的函数指针。只要'virtual_address'处有一个函数,调用约定和签名匹配,就可以执行转换并调用函数。 – red75prime

+0

真棒,我需要做一些更多的设置,看看这是否真的有效,但它确实编译!非常感谢@LukasKalbertodt。 –

相关问题