Можете ли вы преобразовать mut i8 в i32? - PullRequest
0 голосов
/ 21 февраля 2020

Я пытаюсь создать небольшой эмулятор терминала и сталкиваюсь с некоторыми интересными конфликтами типов с lib c. Когда я пытаюсь установить подчиненную часть pty-соединения, мне нужно создать подчиненное устройство с системным вызовом ptsname (), чтобы получить имя для pts, чтобы я мог получить к нему доступ. Тем не менее, я получаю ошибку типа, говорящую, что lib c :: ptsname () требует i32 для ввода. Это находится в прямом конфликте с man-страницей, в которой говорится, что необходимо передать дескриптор файла. Мне просто интересно, смогу ли я преобразовать lib c :: c_int, который у меня есть, для дескриптора файла в i32 для передачи в ptsname.

Код выглядит следующим образом:

use libc::{self, c_int, grantpt, posix_openpt, ptsname, unlockpt, O_RDWR};
use std::os::unix::io::FromRawFd;
use std::process::{Child, Command, Stdio};

#[derive(Debug)]
pub struct Pty {
    process: Child,
    fd: i32,
}

fn create_pty(process: &str) -> Pty {
    let master: c_int;
    unsafe {
        // create master/slave pair of fd
        master = posix_openpt(O_RDWR);
        if master == -1 {
            panic!("Failed to posix_openpt");
        }

        // set slave ownership and mode as master
        let mut result = grantpt(master);
        if result == -1 {
            panic!("Failed to grantpt");
        }
        // unlock slave
        result = unlockpt(master);
        if result == -1 {
            panic!("Failed to unlockpt");
        }
    }
    let slave: c_int = ptsname(master as i32);
    slave = libc::open(slave);

    let mut builder = Command::new(process);

    match builder.spawn() {
        Ok(process) => {
            let pty = Pty {
                process,
                fd: master,
            };

            pty
        }
        Err(e) => {
            panic!("Failed to create pty: {}", e);
        }
    }
}

fn main() {
    let shell = "/bin/bish";

    let pty = create_pty(shell);
    println!("{:?}", pty);
}

и вывод консоли (пока вторая ошибка может быть проигнорирована):

error[E0308]: mismatched types
  --> src/main.rs:42:24
   |
42 |     let slave: c_int = ptsname(master as i32);
   |                        ^^^^^^^^^^^^^^^^^^^^^^ expected i32, found *-ptr
   |
   = note: expected type `i32`
              found type `*mut i8`

error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
  --> src/main.rs:43:13
   |
43 |     slave = libc::open(slave);
   |             ^^^^^^^^^^^^^^^^^ expected at least 2 parameters

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0060, E0308.
For more information about an error, try `rustc --explain E0060`.
error: could not compile `experiment`.

1 Ответ

1 голос
/ 21 февраля 2020

Это не значит, что для этого требуется вход из i32, а скорее, что вы спрашиваете, что ptsname(master as i32); имеет тип i32. Это может немного сбивать с толку, поскольку c_int является псевдонимом для i32, поэтому звучит так, будто он запрашивает не связанный тип.

Проблема в том, что вы задаете slave тип c_int, когда ptsname возвращает *mut c_char (c_char также является псевдонимом, на этот раз для i8).

...