Corretamente sobre-carregamento de um stringbuf para substituir cout em um arquivo mex MATLAB

StackOverflow https://stackoverflow.com/questions/243696

Pergunta

MathWorks atualmente não permite que você use cout de um arquivo mex quando o desktop MATLAB está aberto, porque eles têm redirecionado stdout. Sua solução atual está fornecendo uma função, mexPrintf, que pedem que você usar em vez . Depois de pesquisar um pouco, eu acho que é possível estender a classe std::stringbuf para fazer o que eu preciso. Aqui está o que eu tenho até agora. É este o suficiente robusta, ou existem outros métodos que eu preciso sobrecarga ou uma melhor maneira de fazer isso? (Olhando para a portabilidade em um ambiente geral UNIX ea capacidade de utilização std::cout como normal se este código não está ligada contra um mex executável)

class mstream : public stringbuf {
public:
  virtual streamsize xsputn(const char *s, std::streamsize n) 
  {
mexPrintf("*s",s,n);
return basic_streambuf<char, std::char_traits<char>>::xsputn(s,n);
  }
}; 

mstream mout;
outbuf = cout.rdbuf(mout.rdbuf());    
Foi útil?

Solução

Você realmente não quer std::stringbuf sobrecarga, você quer std::streambuf sobrecarga ou std::basic_streambuf (se você quiser suportar vários tipos de caracteres), também é preciso substituir o método de estouro bem.

Mas também acho que você precisa repensar a sua solução para o seu problema.

cout é apenas um ostream, por isso, se todas as classes / funções leva um ostream então você pode passar em qualquer coisa que você gosta. por exemplo. cout, ofstream, etc

Se isso é muito difícil, então eu iria criar minha própria versão de cout, talvez chamado mycout que pode ser definido em qualquer tempo compilador ou tempo de execução (dependendo do que você quer fazer).

Uma solução simples pode ser:

#include <streambuf>
#include <ostream>

class mystream : public std::streambuf
{
public:
    mystream() {}

protected:
    virtual int_type overflow(int_type c)
    {
        if(c != EOF)
        {
            char z = c;
            mexPrintf("%c",c);
            return EOF;
        }
        return c;
    }

    virtual std::streamsize xsputn(const char* s, std::streamsize num)
    {
        mexPrintf("*s",s,n);
        return num;
    }
};

class myostream : public std::ostream
{
protected:
    mystream buf;

public:
    myostream() : std::ostream(&buf) {}
};

myostream mycout;

E a versão cout só poderia ser:

typedef std::cout mycout;

A versão de tempo de execução é um pouco mais de trabalho, mas facilmente factível.

Outras dicas

Shane, muito obrigado por sua ajuda. Aqui está a minha aplicação de trabalho final.

class mstream : public std::streambuf {
public:
protected:
  virtual std::streamsize xsputn(const char *s, std::streamsize n); 
  virtual int overflow(int c = EOF);
}; 

...

std::streamsize 
mstream::xsputn(const char *s, std::streamsize n) 
{
  mexPrintf("%.*s",n,s);
  return n;
}

int 
mstream::overflow(int c) 
{
    if (c != EOF) {
      mexPrintf("%.1s",&c);
    }
    return 1;
}

...

// Replace the std stream with the 'matlab' stream
// Put this in the beginning of the mex function
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout); 

...

// Restore the std stream buffer 
std::cout.rdbuf(outbuf); 

Eu mudei implementação final do OP um pouco, adicionando um construtor e destruidor. Criando um objeto dessa classe substitui automaticamente o buffer de fluxo em std::cout, e quando o objeto sai do escopo, o buffer de fluxo original é restaurada. RAII!

class mxstreambuf : public std::streambuf {
   public:
      mxstreambuf() {
         stdoutbuf = std::cout.rdbuf( this );
      }
      ~mxstreambuf() {
         std::cout.rdbuf( stdoutbuf );
      }
   protected:
      virtual std::streamsize xsputn( const char* s, std::streamsize n ) override {
         mexPrintf( "%.*s", n, s );
         return n;
      }
      virtual int overflow( int c = EOF ) override {
         if( c != EOF ) {
            mexPrintf( "%.1s", & c );
         }
         return 1;
      }
   private:
      std::streambuf *stdoutbuf;
};

Para usar o buffer de fluxo em um MEX-file, simplesmente:

mxstreambuf mout;
std::cout << "Hello World!\n";

... e não se preocupe em esquecer nada.

cout é um fluxo de saída de caráter particular. Se você quer uma cout que grava em um arquivo, use um fstream , particularmente um ofstream . Eles têm a mesma interface que cout fornece. Além disso, se você quiser pegar o seu tampão (com rdbuf) você pode.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top