使用CString时,使用winapi向控制台写入&str会出错

时间:2018-06-22 18:38:46

标签: winapi console rust ffi

我想使用WriteConsoleOutputAttribute中的the winapi crate&str写入控制台。我只有一个u8数组,它将从结构的std::io::Write实现传递到我的winapi代码。

以下内容无法正常运行,因为我看到的是彩色单元格而不是文本。

use std::ffi::CString;
use std::str;
use winapi::um::wincon::{
    GetConsoleScreenBufferInfo, WriteConsoleOutputAttribute, CONSOLE_SCREEN_BUFFER_INFO, COORD,
};
use winapi::um::winnt::HANDLE;

pub fn write_char_buffer(handle: HANDLE, buf: &[u8]) {
    // get buffer info
    let csbi = get_console_screen_buffer_info();

    // get string from u8[] and parse it to an c_str
    let data = str::from_utf8(buf).unwrap();
    let c_str = CString::new(data).unwrap();
    let ptr: *const u16 = (c_str.as_ptr() as *const u16);

    // get current position
    let current_pos = COORD {
        X: csbi.dwCursorPosition.X,
        Y: csbi.dwCursorPosition.Y,
    };

    let mut cells_written: u32 = 0;

    // write to console
    unsafe {
        WriteConsoleOutputAttribute(
            handle,
            ptr,
            data.len() as u32,
            current_pos,
            &mut cells_written,
        );
    }
}

pub fn get_console_screen_buffer_info() -> CONSOLE_SCREEN_BUFFER_INFO {
    let output_handle = get_output_handle();
    let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
    let success;

    unsafe { success = GetConsoleScreenBufferInfo(output_handle, &mut csbi) }

    if success == 0 {
        panic!("Cannot get console screen buffer info");
    }

    csbi
}

我认为CString和指针出了问题。有关代码,请参见此link

Update

Rust字符串为utf8,而winapi字符串为utf16。因此,我将utf8数组转换为utf16 String,但显示了相同的输出,只是控制台中没有颜色的已整理单元格:

let utf8 = str::from_utf8(buf).unwrap();
let utf16: Vec<u16> = utf8.encode_utf16().collect();
let utf_string = String::from_utf16(&utf16).unwrap();
let c_str = CString::new(utf_string).unwrap();

1 个答案:

答案 0 :(得分:2)

  

我想使用&strWriteConsoleOutputAttribute写入控制台

那不是该功能的作用。 WriteConsoleOutputAttribute设置字符属性:诸如背景色,前景色,下划线之类的内容。 This page有一个(更多)完整列表。

要将文字写入控制台,请在将其转换为UTF-16后使用WriteConsoleOutputCharacter