如何从视觉工作室将stdout重定向到输出窗口

Mir*_*pas 21 c++ visual-studio-2010 visual-studio

是否可以将stdout重定向到Visual Studio的输出窗口?我在我的程序OutputDebugString中使用但是我使用了一些带有printf或cout输出调试消息的库.

Ozi*_*rus 10

来自https://web.archive.org/web/20140825203329/http://blog.tomaka17.com/2011/07/redirecting-cerr-and-clog-to-outputdebugstring/:

#include <ostream>
#include <Windows.h>

/// \brief This class is derives from basic_stringbuf which will output
/// all the written data using the OutputDebugString function
template<typename TChar, typename TTraits = std::char_traits<TChar>>
class OutputDebugStringBuf : public std::basic_stringbuf<TChar,TTraits> {
public:
    explicit OutputDebugStringBuf() : _buffer(256) {
        setg(nullptr, nullptr, nullptr);
        setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
    }

    ~OutputDebugStringBuf() {
    }

    static_assert(std::is_same<TChar,char>::value ||
                    std::is_same<TChar,wchar_t>::value,
                  "OutputDebugStringBuf only supports char and wchar_t types");

    int sync() try {
        MessageOutputer<TChar,TTraits>()(pbase(), pptr());
        setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
        return 0;
    }
    catch(...) {
        return -1;
    }

    int_type overflow(int_type c = TTraits::eof()) {
        auto syncRet = sync();
        if (c != TTraits::eof()) {
            _buffer[0] = c;
            setp(_buffer.data(), _buffer.data() + 1, _buffer.data() + _buffer.size());
        }
        return syncRet == -1 ? TTraits::eof() : 0;
    }


private:
    std::vector<TChar> _buffer;

    template<typename TChar, typename TTraits>
    struct MessageOutputer;

    template<>
    struct MessageOutputer<char,std::char_traits<char>> {
        template<typename TIterator>
        void operator()(TIterator begin, TIterator end) const {
            std::string s(begin, end);
            OutputDebugStringA(s.c_str());
        }
    };

    template<>
    struct MessageOutputer<wchar_t,std::char_traits<wchar_t>> {
        template<typename TIterator>
        void operator()(TIterator begin, TIterator end) const {
            std::wstring s(begin, end);
            OutputDebugStringW(s.c_str());
        }
    };
};
Run Code Online (Sandbox Code Playgroud)

然后:

int main() {
    #ifndef NDEBUG
        #ifdef _WIN32
            static OutputDebugStringBuf<char> charDebugOutput;
            std::cerr.rdbuf(&charDebugOutput);
            std::clog.rdbuf(&charDebugOutput);

            static OutputDebugStringBuf<wchar_t> wcharDebugOutput;
            std::wcerr.rdbuf(&wcharDebugOutput);
            std::wclog.rdbuf(&wcharDebugOutput);
        #endif
    #endif

    ...

    // Will be displayed in the debugger
    std::cerr << "Error: something bad happened" << std::endl;

    ...
}
Run Code Online (Sandbox Code Playgroud)

你可能想用它

的IsDebuggerPresent()

这样当它不从Visual Studio调试器运行时它仍然输出到控制台.


Sum*_*uma 3

直接的标准输出重定向将不起作用,因为没有与 OutputDebugString 对应的句柄。不过,应该有办法:

可以通过将标准输出重定向到管道,然后创建一个线程来读取管道并使用 OutputDebugString 打印从管道中读取的任何内容来完成。

注意:我很久以前就在考虑实现这个,因为我面临着与你完全相同的问题(一些库使用 printf 或 fprintf(stderr....)。但是,我从来没有真正这样做过。我一直相反,我结束了对库的修改,因此我没有有效的实现,但我认为原则上应该是可行的。