Правильная перегрузка stringbuf для замены cout в mex-файле MATLAB.

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

Вопрос

MathWorks в настоящее время не позволяет вам использовать cout из файла mex, когда рабочий стол MATLAB открыт, потому что они перенаправили стандартный вывод.Их текущий обходной путь — предоставление функции, mexPrintf, который они просят использовать вместо него.Немного погуглив, я думаю, что можно расширить std::stringbuf класс, чтобы делать то, что мне нужно.Вот что у меня есть на данный момент.Достаточно ли это надежно, или мне нужно перегрузить другие методы или лучший способ сделать это?(Ищете переносимость в общей среде UNIX и возможность использовать std::cout как обычно, если этот код не связан с исполняемым файлом mex)

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());    
Это было полезно?

Решение

Вы действительно не хотите перегружать std :: stringbuf , вы хотите перегрузить std :: streambuf или std :: basic_streambuf (если вы хотите поддерживать несколько типов символов), вам также необходимо переопределить метод переполнения.

Но я также думаю, что вам нужно переосмыслить решение вашей проблемы.

cout - это просто ostream , поэтому, если все классы / функции принимают ostream , вы можете передать все, что захотите. например cout , ofstream и т. д.

Если это слишком сложно, я бы создал свою собственную версию cout , которая может называться mycout , которую можно определить во время компиляции или во время выполнения (в зависимости от того, что вы хочу сделать).

Простое решение может быть следующим:

#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;

И версия cout может быть просто:

typedef std::cout mycout;

Версия во время выполнения немного сложнее, но легко выполнима.

Другие советы

Шейн, большое спасибо за твою помощь.Вот моя последняя рабочая реализация.

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); 

Я немного изменил окончательную реализацию OP, добавив конструктор и деструктор. Создание объекта этого класса автоматически заменяет потоковый буфер в std :: cout , а когда объект выходит из области видимости, исходный потоковый буфер восстанавливается. 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;
};

Чтобы использовать потоковый буфер в MEX-файле, просто:

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

... и не беспокойся о том, чтобы что-то забыть.

cout - это поток вывода конкретного символа. Если вам нужен cout , который пишет в файл, используйте < code> fstream , в частности ofstream . Они имеют тот же интерфейс, что и cout . Кроме того, если вы хотите получить их буфер (с помощью rdbuf ), вы можете.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top