How to capture C's stdout/stderr

I'm writing a GUI program on Windows which needs to call some functions implemented in an external C library. Unfortunately, these functions print out messages into stdout and stderr then I need to redirect/capture them to my own handler.

There are several helps and they are around using open_osfhandle to redirect stdout and stderr to Windows's HANDLE.

But I still don't know how to obtain these C's IO handler in Rust. Many thanks for any help.

You could use the winapi crate for SetStdHandle to change stdin/out/err into pipes, convert the pipes into a Stdio using the FromRawHandle trait.

Full example using WinAPI (in C): https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output?redirectedfrom=MSDN

1 Like

Thank you, but the problem is how to access stdin/out/err. They are IO handlers create by Windows CRT, I found that they are defined in corecrt_wstdio.h as:

#define stdin  (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

I've found a tricky way using:

#[link(name = "ucrt")]
extern "C" {
    fn __acrt_iob_func(fileno: u32) -> *mut FILE;
}
...
let stdout = __acrt_iob_func(1);

You can also use cc crate: https://crates.io/crates/cc write function to disable stdout/stderr on C and just call it from Rust.

If you have Windows HANDLE, you can use https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html to make it a libstd's File or stdio stream.

Similarly you can take a Rust pipe or File, and get HANDLE out of it: https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html

1 Like

SetStdHandleEx also gives you the previous handle, so you can capture what you need and later switch back to the original handles

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.