Правильная перегрузка строкового буфера для замены cout в файле MATLAB mex

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());    
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
3 345
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

cout - это поток вывода определенного символа. Если вам нужен cout, который записывает в файл, используйте fstream, особенно ofstream. У них тот же интерфейс, что и у cout. Кроме того, если вы хотите получить их буфер (с помощью 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); 

Восстановление буфера потока std оказалось очень важным. Без этого у моей функции mex, похоже, возникла какая-то проблема с памятью и произошел сбой matlab при reсоставление.

Alec Jacobson 27.12.2012 22:18

Я немного изменил окончательную реализацию 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";

... и не бойтесь ничего забыть.

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