views:

38

answers:

1

I have a C++ DLL that I have source to. It is currently logging to stdout.

I am calling methods in this dll via pinvoke from c#.

I want the c# code to be able to get the log messages, and then forward them to the c# application's own logging mechanism.

I have seen some questions/answers dealing with capturing stdout, but I cannot get them to work. If someone can provide a complete hello world example for this, that would be great.

Otherwise, I was thinking of changing the c++ function to accept a string or stream parameter of some sort and just fill it with messages to be read at the return of the function.

However, how do I use string, since the c++ dll would need to allocate the memory, and what would free it?

Is there a way for me to pass in a stream and read from the stream using normal c# stream mechanics, but inside the dll let it be used just like stdout would be normally?

Help!

This question is close, but I dont want to write it out to a file, if something similar would work to capture into a memorystream that would be great, but I don't see an equivilent SafeHandle etc for memorystream. http://stackoverflow.com/questions/1579074/redirect-stdoutstderr-on-c-windows-service

A: 

You could declare your logging function in your C++ DLL as a function pointer, which defaults to a function printing to stdout, and provide a P/Invoke'able function to set it to a different callback.
You can pass a C# method to this function by using Marshal.GetFunctionPointerForDelegate.

Example (untested!)

C++ DLL (pseudo-code):

delegate void logger(char* msg);

logger log = printf;

void set_logger(logger l) {
    log = l;
}

void test() {
    log("Hello World!");
}

C# program:

static extern void set_logger(IntPtr l);

static extern void test();

static Action<IntPtr> log;

static void LogToConsole(IntPtr msg)
{
    Console.WriteLine(Marshal.PtrToStringAnsi(msg));
}

static void Main()
{
    log = new Action<IntPtr>(LogToConsole);
    set_logger(Marshal.GetFunctionPointerForDelegate(log));

    test();
}
dtb
This will bomb pretty quickly when the garbage collector collects the Action<> delegate instance.
Hans Passant
The remember the Action<> delegate instance somewhere :-) ... The example is far from perfect, it just shows a general idea how it might be done.
dtb