c++ - Sobrecargar correctamente un stringbuf para reemplazar cout en un archivo MATLAB mex
stringbuffer (4)
En realidad, no desea sobrecargar std :: stringbuf, desea sobrecargar std :: streambuf o std :: basic_streambuf (si desea admitir varios tipos de caracteres), también debe anular el método de desbordamiento.
Pero también creo que debes replantear tu solución a tu problema.
cout es solo un ostream, entonces si todas las clases / funciones toman un ostream entonces puedes pasar lo que quieras. por ejemplo, cout, ofstream, etc.
Si eso es demasiado difícil, entonces crearía mi propia versión de cout, quizás llamada mycout, que se puede definir en tiempo de compilación o en tiempo de ejecución (dependiendo de lo que desee hacer).
Una solución simple puede 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;
Y la versión cout podría ser:
typedef std::cout mycout;
Una versión en tiempo de ejecución es un poco más de trabajo pero fácilmente realizable.
MathWorks actualmente no le permite usar cout desde un archivo mex cuando el escritorio de MATLAB está abierto porque han redirigido stdout. Su solución actual es proporcionar una función, mexPrintf, que le piden que use en su lugar . Después de buscar en Google un poco, creo que es posible extender la clase std :: stringbuf para hacer lo que necesito. Esto es lo que tengo hasta ahora. ¿Es esto lo suficientemente robusto, o hay otros métodos que debo sobrecargar o una mejor manera de hacerlo? (Buscando la portabilidad en un entorno general de UNIX y la capacidad de utilizar std :: cout de forma normal si este código no está vinculado a un ejecutable 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());
Shane, muchas gracias por tu ayuda. Aquí está mi implementación final de trabajo.
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);
He cambiado un poco la implementación final del OP, añadiendo un constructor y un destructor. La creación de un objeto de esta clase reemplaza automáticamente el almacenamiento intermedio de flujo en std::cout
, y cuando el objeto sale del alcance, se restablece el almacenamiento intermedio de flujo original. ¡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 el almacenamiento intermedio de flujo en un archivo MEX, simplemente:
mxstreambuf mout;
std::cout << "Hello World!/n";
... y no te preocupes por olvidar nada.