DBG vs printf & std::cout


#1

A quick test reveals DBG("foo\n") succeeds whereas printf & std::cout produce no console output (testing in Visual Studio, normally I would use OSX but this rotten eyetracker only works on Windows).

It's strange, I thought I remembered noting std::cout working a few days back...

Does this mean JUCE is hijacking console output?

How would I handle something like:

printf( "x,y = %.1f, %.1f\n", x, y );

?

π


#2

If you look at the code for JUCE's DBG macro, under Visual Studio it streams to a Windows specific API that makes it print to the VS "output" pane since there's no standard console for printf() or std::cout to print to under the Windows subsystem which Windows JUCE applications use.

If I have to use my own stringstream object instead of the DBG macro, (for example if I wanted to print a bunch of things in a for loop without a newline every time, which DBG always sticks on the end) I usually just make an std::ostringstream object, push stuff into it like I would std::cout, then before it goes out of scope and disappears use DBG(<ostringstream_var>.str()) to print it out to VS's output.


#3

Using http://stackoverflow.com/questions/69738/c-how-to-get-fprintf-results-as-a-stdstring-w-o-sprintf#69911


// http://stackoverflow.com/questions/69738/c-how-to-get-fprintf-results-as-a-stdstring-w-o-sprintf#69911
#include <string>
#include <cstdarg>
#include <vector>
#include <string>
#include <cstdarg>
class PiString
{
private:
    static 
    std::string
    vformat(const char *fmt, va_list ap)
    {
        // Allocate a buffer on the stack that's big enough for us almost
        // all the time.  Be prepared to allocate dynamically if it doesn't fit.
        size_t size = 1024;
        char stackbuf[1024];
        std::vector<char> dynamicbuf;
        char *buf = &stackbuf[0];
        while (1) {
            // Try to vsnprintf into our buffer.
            int needed = vsnprintf(buf, size, fmt, ap);
            // NB. C99 (which modern Linux and OS X follow) says vsnprintf
            // failure returns the length it would have needed.  But older
            // glibc and current Windows return -1 for failure, i.e., not
            // telling us how much was needed.
            if (needed <= (int)size && needed >= 0) {
                // It fit fine so we're done.
                return std::string(buf, (size_t)needed);
            }
            // vsnprintf reported that it wanted to write more characters
            // than we allotted.  So try again using a dynamic buffer.  This
            // doesn't happen very often if we chose our initial size well.
            size = (needed > 0) ? (needed + 1) : (size * 2);
            dynamicbuf.resize(size);
            buf = &dynamicbuf[0];
        }
    }
public:
    static 
    std::string
    format(const char *fmt, ...)
    {
        va_list ap;
        va_start(ap, fmt);
        std::string buf = vformat(fmt, ap);
        va_end(ap);
        return buf;
    }
};

I can do the following:

#define DBG2(...) DBG( PiString::format(__VA_ARGS__ ) )

DBG2("Gaze Data: (%.1f, %.1f) timestamp %.0f ms\n", eventParams.X, eventParams.Y, eventParams.Timestamp);

π

PS Alternatively:

#include <sstream>
#include <iomanip> // std::setprecision

std::ostringstream s;
s << "x=" << std::setprecision(3) << eventParams.X;
DBG( s.str() );

but .. yuck!


#4

Hello forum people! Upgrading the forum has produced artefacts in old code. This makes a lot of old code unreadable.

It needs a script to run through the database doing a search&replace.

I’ve mentioned this 3 or 4 times… I hope someone is listening!

π


#5

Also, nobody has said where printf output actually DOES go.

Say I’m using a third-party C library – I don’t want to have to rework every line involving printf.

Is there some way to access the output?

π


#6

@_pi

On Windows, the answer is usually “nowhere”.

See How does JUCE redirect stdout?