gpt4 book ai didi

windows - 如何将非缓冲写入标准输出?

转载 作者:行者123 更新时间:2023-12-03 11:47:55 24 4
gpt4 key购买 nike

我需要20个“H”字符以1秒的间隔出现。这个程序什么也没显示到最后

use std::io::Write;
use std::time::Duration;
fn main() {
let ch = 'H' as u8;
for _ in 0..20 {
let buff = vec![ch];
std::io::stdout().write(&buff).unwrap();
std::io::stdout().flush().unwrap();
std::thread::sleep(Duration::from_millis(1000));
}
}
这个等效的C++程序可以正常工作
#include <iostream>
#include <Windows.h>

int main()
{
for(int i = 0; i < 20; i++)
{
std::cout << (char)'H';
std::cout.flush();
Sleep(1000);
}
}
我尝试过crossterm,但无法完成这项工作,但看起来确实很有趣。我尝试了crossterm_winapi,它直接调用了 WriteConsoleW,但后来却没有任何输出。

最佳答案

我将回答我自己的问题,因为我在这里经历了很多发现,并且我相信其他人也会发现它有用。
顺便说一句-原始问题在注释部分中出了错,解释了为什么我的c++等效文件(不带刷新)工作/不工作/不应该工作/可能工作。让我们忽略它-我添加了同花顺。
首先调试
vscode和Vs2019会使用stdout进行处理,以尝试有所帮助。在大多数情况下,它是有帮助的,但在这种情况下无济于事
vscode窃取标准输出,使其显示在终端窗口中。通常,这将被定向到控制台窗口。无论您使用冲洗等如何操作,它都将施加自己的缓冲。
我的rust代码的真正目的是一个将rust代码称为cdylib的C#gui应用程序。最初,该dll是用C++编写的。在运行GUI应用程序时,vs2019还窃取了stdout(对于控制台应用程序则不是这种情况,与上面的我的迷你C++代码无关),因此它可以在``输出''窗口中显示它。
当然,如果应用程序在调试器之外运行,这两种行为都会消失。但这使调试变得困难。
这当然使我的很多研究感到困惑,因为在不同的情况下我没有看到输出,因为我找错了地方。
解决方案1 ​​
如果您通过控制台窗口中的商品运行它,那么我问题中的原始代码实际上可以正常工作。出色的。如果从内部运行,vscode会将其全部缓冲-所以不要那样做。
问题2,没有控制台窗口
Windows gui应用程序启动“知道”该程序不需要控制台窗口,因此将stdout通过管道传送到bitbucket。我在C#-> c++版本中遇到了同样的问题。这里的 secret 是创建一个控制台窗口并将stdout重新附加到它。
解决方案2
到达winapi crate 。

  unsafe {
let ff = winapi::um::wincon::FreeConsole();
let ret = winapi::um::consoleapi::AllocConsole();
let err = winapi::um::errhandlingapi::GetLastError();
};
如果我们连接到一些奇怪的东西,FreeConsole只是为了分离。然后,AllocConsole创建一个控制台窗口并将该进程连接到该窗口,但尚未连接任何东西。因此,现在将新的控制台窗口连接到stdout:
let file = OpenOptions::new().write(true).read(true).open("CONOUT$").unwrap();
unsafe{
let err = winapi::um::processenv::SetStdHandle(winapi::um::winbase::STD_OUTPUT_HANDLE, file.as_raw_handle());
}
CONOUT $是所连接控制台窗口的输出缓冲区的特殊名称。 SetStdHandle将其连接到stdout。
现在,在gui旁边弹出一个新窗口,所有stdout写入均显示在其中-哇。
这也适用于vscode调试。出现一个新的“dos”窗口,并且在那里出现标准输出。额外的好处
问题3需要较低级别的访问权限
在我最初使用C++编写的PDP引擎中,我仍然不满意仍然使用std::cout,我需要尽可能接近Windows控制台子系统(我正在模拟PDP的原始物理设备的行为)。因此,我决定在此新版本中使用直接Windows IO
解决方案3
因此,仍然使用AllocConsole并打开CONOUT $,但调用控制台直接写
  let buff: [u8; 1] = [ch];
let ptr: *const c_void = buff.as_ptr() as *const _ as *const c_void;

let mut cells_written: u32 = 0;
// write to console
unsafe {
WriteConsoleA(
file.as_raw_handle(),
ptr,
1,
&mut cells_written,
NULL,
) ;
};
文件是打开CONOUT $的句柄返回
效果很好。我知道我有时需要对stdin/CONIN $做同样的事情

关于windows - 如何将非缓冲写入标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63590925/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com