Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect native DLL stdout/stderr from managed wrapper

I have a C# Console app that P/Invokes into a native C++ dll. The dll creates some threads which are very chatty and write their logs into standard outputs. The problem is that I need Console for my user interactions.

How can I redirect the dll stdout/stderr to null?

like image 228
MBZ Avatar asked Nov 22 '22 23:11

MBZ


1 Answers

I think than, in order to make this work you will need to build a native DLL that links to the same C++ runtime as the troublesome DLL. You'll then need to use freopen to redirect the stdout. My source for this code is this answer: freopen: reverting back to original stream

The C++ code would look like this:

#include <io.h>

__declspec(dllexport) void RedirectStdOutputToNul(int *fd, fpos_t *pos)
{
    fflush(stdout);
    fgetpos(stdout, pos);
    *fd = _dup(fileno(stdout));
    freopen("NUL", "w", stdout);
}

__declspec(dllexport) void RestoreStdOutput(int fd, fpos_t pos)
{
    fflush(stdout);
    _dup2(fd, fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);      
}

You can p/invoke that from your code like this:

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern void RedirectStdOutputToNul(out int fd, out long pos);

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern void RestoreStdOutput(int fd, long pos);

And you might call it like this:

int fd;
long pos;

RedirectStdOutputToNul(out fd, out pos);
print("boo");
RestoreStdOutput(fd, pos);
print("yah");

All this relies upon the DLL linking to a dynamic MSVC runtime and you being able to write code that links to same.

like image 113
David Heffernan Avatar answered Dec 21 '22 23:12

David Heffernan