写作a&;使用CString时,使用winapi将str发送到控制台时出错

写作a&;使用CString时,使用winapi将str发送到控制台时出错,winapi,console,rust,ffi,Winapi,Console,Rust,Ffi,我想使用from将&str写入控制台。我只有一个u8数组,它将从结构的std::io::Write实现传递到我的winapi代码 以下内容无法正常工作,因为我看到的是彩色单元格而不是文本 use std::ffi::CString; use std::str; use winapi::um::wincon::{ GetConsoleScreenBufferInfo, WriteConsoleOutputAttribute, CONSOLE_SCREEN_BUFFER_INFO, COOR

我想使用from将
&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
和指针出了问题。查看此代码

Rust字符串是utf8,而winapi字符串是utf16。因此,我将utf8数组转换为utf16字符串,但显示的是相同的输出,只是控制台中的单元格不带文本:

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();
让utf8=str::from_utf8(buf).unwrap();
让utf16:Vec=utf8.encode_utf16().collect();
让utf_string=string::from_utf16(&utf16).unwrap();
让c_str=CString::new(utf_string).unwrap();
我想使用
WriteConsoleOutputAttribute
向控制台写入
&str

这不是函数的作用
WriteConsoleOutputAttribute
设置字符属性:背景色、前景色、下划线等。有一个(更)完整的列表

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

我想使用
WriteConsoleOutputAttribute
向控制台写入
&str

这不是函数的作用
WriteConsoleOutputAttribute
设置字符属性:背景色、前景色、下划线等。有一个(更)完整的列表


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

我已经读过,但我发现在创建CString时应在同一行上调用unwrap。我来看看。好的,我已经把它绑定到一个局部变量上了。这似乎不起作用。指针的值为“
”0x1c57fa2c0a0”
。此外,cstring不是
ERR
。我在控制台中看不到字符,但每个字符都有一个彩色cel。你发送的链接不适用于我的情况。我可以解释为什么我的问题不是重复的:1:我不想把cstring转换回来。2:指针不为空3:情况并非如此,我已经修复了代码,但仍然会导致错误。4:很遗憾,最后一个链接不适用于我的问题。我相信你的问题已经由的答案回答了。如果你不同意,请用你的问题来解释不同之处。否则,我们可以将此问题标记为已回答。TL;重复:生锈的字符串是UTF-8。Windows需要UTF-16。感谢您的解决方案,这可能是问题所在,但输出中没有差异。这就是我如何将u8数组转换为字符串的方法,对吗<代码>让utf8=str::from_utf8(buf).unwrap();让utf16:Vec=utf8.encode_utf16().collect();让utf_string=string::from_utf16(&utf16).unwrap()我已经读过了,但是我看到在创建CString时应该在同一行上调用unwrap。我来看看。好的,我已经把它绑定到一个局部变量上了。这似乎不起作用。指针的值为“
”0x1c57fa2c0a0”
。此外,cstring不是
ERR
。我在控制台中看不到字符,但每个字符都有一个彩色cel。你发送的链接不适用于我的情况。我可以解释为什么我的问题不是重复的:1:我不想把cstring转换回来。2:指针不为空3:情况并非如此,我已经修复了代码,但仍然会导致错误。4:很遗憾,最后一个链接不适用于我的问题。我相信你的问题已经由的答案回答了。如果你不同意,请用你的问题来解释不同之处。否则,我们可以将此问题标记为已回答。TL;重复:生锈的字符串是UTF-8。Windows需要UTF-16。感谢您的解决方案,这可能是问题所在,但输出中没有差异。这就是我如何将u8数组转换为字符串的方法,对吗<代码>让utf8=str::from_utf8(buf).unwrap();让utf16:Vec=utf8.encode_utf16().collect();让utf_string=string::from_utf16(&utf16).unwrap()谢谢,这可能是解决方案。“WriteConsoleOutputAttribute”的描述是:从指定位置开始,将许多字符属性复制到控制台屏幕缓冲区的连续单元格。我没有看到“attribute”这个词,我将尝试一下。它现在可以工作了,我使用函数
WriteConsoleOutputCharacterA
。谢谢,这可能是解决方案。“WriteConsoleOutputAttribute”的描述是:从指定位置开始,将多个字符属性复制到控制台屏幕缓冲区的连续单元格。“我没有看到“attribute”这个词,我将尝试一下。它现在可以工作了,我使用函数
WriteConsoleOutputCharacterA