Что делает transmute :: <* mut c_void, Option() >> значит? - PullRequest
0 голосов
/ 20 апреля 2019

Вот некоторый код, который я сгенерировал, используя c2rust , а затем немного очистил:

#![feature(libc)]
extern crate libc;

use libc::*;
use std::mem::transmute;

extern "C" {
    #[no_mangle]
    fn read(__fd: c_int, __buf: *mut c_void, __nbytes: c_ulong) -> c_long;
    #[no_mangle]
    fn mmap(
        __addr: *mut c_void,
        __len: c_ulong,
        __prot: c_int,
        __flags: c_int,
        __fd: c_int,
        __offset: c_long,
    ) -> *mut c_void;
}

pub fn main() {
    unsafe {
        let buf: *mut c_void = mmap(
            0 as *mut c_void,
            256i32 as c_ulong,
            0x1i32 | 0x2i32 | 0x4i32,
            0x2i32 | 0x20i32,
            -1i32,
            0i32 as c_long,
        );
        read(0i32, buf, 256i32 as c_ulong);
        transmute::<*mut c_void, Option<unsafe extern "C" fn() -> ()>>(buf).unwrap()();
    }
}

Хотя я понимаю, что он делает, я не уверен, как интерпретировать последнее выражение,Что означает Option<unsafe extern "C" fn() -> ()>?

1 Ответ

0 голосов
/ 20 апреля 2019

Мы пытаемся вызвать unsafe extern "C" fn() -> (), который в основном является функцией без аргументов и без возвращаемого типа. Моей первой попыткой было просто использовать ключевое слово as, как определено в документации transmute. Я получил следующую ошибку:

error[E0605]: non-primitive cast: `*mut libc::c_void` as `unsafe extern "C" fn()`
  --> wx.rs:32:9
   |
32 |         (buf as unsafe extern "C" fn() -> ())();
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

Похоже, функция не примитивного типа, и поэтому мне нужно transmute. Я попробовал следующее:

transmute::<
    *mut c_void,
    unsafe extern "C" fn() -> ()
>(buf)();

И код скомпилирован и фактически работает как ожидалось.

Что я до сих пор не понимаю, так это то, почему Option использовался c2rust, но без него код работает нормально. Похоже, что unsafe и extern "C" также можно удалить, и код все еще работает, по крайней мере, для меня.

...