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