:::: MENU ::::

3 способа перенаправить std::cout (iostream, streambuf, cout, IAR, __write)

Часто, работая с микроконтроллерами на С++, приходится изменять вывод std::cout. Например направить его в USART, на дисплей или просто в буфер. В данной статье будет описано 3 способа изменения вывода — два универсальных и один для IAR.

Первый способ — создать свой класс, наследуемый от streambuf и реализовать в нем виртуальный метод overflow, при этом указав буфер для хранения данных на передачу нулевого размера. И указать на экземпляр этого класса, для стандартного вывода cout.

out_buf the_out_buf;    
cout.rdbuf(&the_out_buf);

Тогда, когда вы будете вызывать, cout << any будет вызываться метод overflow (т.к. буфер нулевого размера). Данный метод будет вызываться для каждого символа передаваемого на вывод и вам нужно просто написать свою процедуру обработки этих данных.

test.h

#include <streambuf>  

class out_buf: public streambuf {
public:
    out_buf();
    char out_ch;

private:    
    virtual int overflow(int ch);
    char *tmp;
};

out_buf::out_buf()
{
    // устанавливаем  нулевой размер буфера
    setp(tmp, tmp);  // начало = концу буфера
}

int out_buf::overflow(int ch)
{ 
    out_ch = (char)ch;
}

main.c

#include <iostream>
#include "test.h"

int main(void)
{
    out_buf the_out_buf;    
    cout.rdbuf(&the_out_buf);

    cout << "test";
    cout << endl;
{

Второй способ — полностью заменить cout своим классом (через макрос — см. код). При данном подходе, необходимо написать методы для всех типов данных передаваемых в cout.

debug_out.h

#define cout DebugOut::GetCurrentDebugOut()
#define endl DebugOut::endl

class DebugOut
{
public:
    DebugOut();
    ~DebugOut();

    void putChar( char ch );

    friend DebugOut& operator <<( DebugOut& rOs, unsigned char bChar );
    friend DebugOut& operator <<( DebugOut& rOs, unsigned short integer );
    friend DebugOut& operator <<( DebugOut& rOs, unsigned int integer );
    friend DebugOut& operator <<( DebugOut& rOs, char bChar );
    friend DebugOut& operator <<( DebugOut& rOs, short integer );
    friend DebugOut& operator <<( DebugOut& rOs, int integer );

    friend DebugOut& operator <<( DebugOut& rOs, void* ptr );
    friend DebugOut& operator <<( DebugOut& rOs, const char* pString );

    DebugOut& operator<<( DebugOut& (*_f)( DebugOut& ) );
    static DebugOut& endl(DebugOut& rOs);
    static DebugOut& GetCurrentDebugOut();
};

debug_out.cpp

#include "debug_out.h"
#include <stdio.h>

static DebugOut iar_cout;

DebugOut::DebugOut(void){}
DebugOut::~DebugOut(void){}

void DebugOut::putChar( char ch )
{
    printf("%c", ch);
}

DebugOut& operator <<( DebugOut& rOs, unsigned char bChar )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, unsigned short integer )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, unsigned int integer )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, char bChar )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, short integer )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, int integer )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, void* ptr )
{
    return rOs;
}

DebugOut& operator <<( DebugOut& rOs, const char* pString )
{
    while(*pString != 0)
    {
        rOs.putChar( *pString);
        pString++;
    }
    return rOs;
}

DebugOut & DebugOut::operator<< (DebugOut & (*_f)(DebugOut &))
{
    return(*_f)(*this);
}

DebugOut& DebugOut::endl(DebugOut & rOs) 
{
    rOs.putChar(0x0A);
    return rOs;
}

DebugOut& DebugOut::GetCurrentDebugOut()
{
    return iar_cout;
}

main.c

#include "debug_out.h"

int main(void)
{    
    cout << "test" << endl;
    cout << endl;
    cout << "test";
}

Третий способ — специализирован для IAR.

В папке где установлен IAR, найти \arm\src\lib\write.c. Данный файл подключить к проекту и переписать код в функции

size_t __write(int handle, const unsigned char * buffer, size_t size)
{
}

на необходимый.

При вызове cout будет вызваться данная функция.