tags:

views:

386

answers:

4

i have a bunch of Console.WriteLines in my code that I can observe at runtime. I communicate with a native library that I also wrote.

I'd like to stick some printf's in the native library and observe them too. I don't see them at runtime however.

I've created a convoluted hello world app to demonstrate my problem. When the app runs, I can debug into the native library and see that the hello world is called. The output never lands in the textwriter though. Note that if the same code is run as a console app then everything works fine.

C#:

    [DllImport("native.dll")]
    static extern void Test();

    StreamWriter writer;

    public Form1()
    {
        InitializeComponent();

        writer = new StreamWriter(@"c:\output.txt");
        writer.AutoFlush = true;
        System.Console.SetOut(writer);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Test();
    }

and the native part:

__declspec(dllexport) void Test()
{
    printf("Hello World");
}

Update: hamishmcn below started talking about debug/release builds. I removed the native call in the above button1_click method and just replaced it with a standard Console.WriteLine .net call. When I compiled and ran this in debug mode the messages were redirected to the output file. When I switched to release mode however the calls weren't redirected. Console redirection only seems to work in debug mode. How do I get around this?

+1  A: 

I don't currently have any project I could try this on but I would definitely suspect buffering. stdout is buffered if my memory serves me right. It flushes buffer every time it hits the end of line:

printf("Should be flushed immediatelly\n");

Or you can use fflush to flush the stdout:

printf("Will be buffered and then flushed");
fflush(stdout);

You can also turn buffering off by using setbuf:

setbuf(stdout, NULL);
CodeRipper
I just tried your suggestions but with no luck :(
Matt Jacobsen
+2  A: 

Perhaps your native library, for some reason, doesn't know about the console.
You could try calling GetConsole an see if a handle is returned. If not you could try allocating your own console to see if that works.
Good luck! :-)


Update:
I wrote a sample app too (console C# app calling native C++ dll) and both the C# Console.WriteLine and the native printf appear on the console... So what are we missing?
Do you always run it in debug mode - do you see a console window at all if you run it in release mode?
Update 2:
Sorry, I should say I see the text on the console, but if I set the Console output to a StreamWriter, like you have in your example, then only the WriteConsole text goes to the output file, the printfs still go to the screen

hamishmcn
I updated my question based on your suggestions.
Matt Jacobsen
See also http://stackoverflow.com/questions/432832/what-is-the-different-between-api-functions-allocconsole-and-attachconsole-1
abatishchev
abatishchev: that's yet another random function call. Don't mean to be funny, but what is really wrong with my simple printf calls in the first place?
Matt Jacobsen
interesting, did you try AllocConsole(), to see if it worked then?
hamishmcn
no, I called GetStdHandle, which returned a valid handle to a console. As I understand it, I don't need to call AllocConsole
Matt Jacobsen
Matt Jacobsen
Which means, that trying for WriteConsole is of no use :)
Matt Jacobsen
I wrote a sample app too (console C# app calling native C++ dll) and both the C# Console.WriteLine and the native printf appear on the console... So what are we missing?... Do you always run it in debug mode - do you see a console window at all if you run it in release mode?
hamishmcn
I always run the native library in release mode, the reason being that a debug release of a native library never runs on a non-dev machine.
Matt Jacobsen
A: 

Implement your own printf (on top of vsnprintf to take care of the dirty details) that writes to the console:

#include <stdarg.h>

int printf(const char *fmt, ...)
{
    char buffer[LARGESIZE];
    int rv;
    va_list ap;
    va_start(ap, fmt);
    rv = vsnprintf(buffer, sizeof(buffer), fmt, ap);
    va_end(ap);

    Console.WriteLine(buffer);

    return rv;
}
R Samuel Klatchko
Nice idea. Just don't call it `printf()` (simply because it isn't).
DevSolar
A: 

Console redirection only works in debug mode.

Matt Jacobsen