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. Redirect stdout+stderr on a C# Windows service

3
  • Have you considered migrating to C++/CLI? Commented Aug 9, 2010 at 18:46
  • c++/CLI wont work in this instance. We are ultimately calling out to a c++ com library Commented Aug 9, 2010 at 18:50
  • 1
    Speaking from recent painful experience, I'd not advise anyone to use C++/CLI unless they literally have no alternative. Commented Dec 15, 2012 at 16:59

1 Answer 1

1

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();
}
Sign up to request clarification or add additional context in comments.

2 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.