Sovraccaricare correttamente un stringbuf per sostituire cout in un file mex MATLAB
-
04-07-2019 - |
Domanda
Attualmente MathWorks non ti consente di utilizzare cout
da un file mex quando il desktop MATLAB è aperto perché hanno reindirizzato stdout. La loro soluzione alternativa attuale sta fornendo una funzione, mexPrintf, che ti richiedono invece di utilizzare . Dopo aver cercato su Google un po ', penso che sia possibile estendere la classe std :: stringbuf
per fare ciò di cui ho bisogno. Ecco cosa ho finora. È abbastanza robusto o ci sono altri metodi che devo sovraccaricare o un modo migliore per farlo? (Alla ricerca della portabilità in un ambiente UNIX generale e della possibilità di utilizzare std :: cout
normalmente se questo codice non è collegato a un eseguibile 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());
Soluzione
Non vuoi davvero sovraccaricare std :: stringbuf
, vuoi sovraccaricare std :: streambuf
o std :: basic_streambuf
(se desideri supportare più tipi di caratteri), devi anche sovrascrivere il metodo di overflow.
Ma penso anche che tu debba ripensare la tua soluzione al tuo problema.
cout
è solo un ostream
, quindi se tutte le classi / funzioni accettano un ostream
, puoi passare qualsiasi cosa tu voglia. per esempio. cout
, ofstream
, ecc.
Se è troppo difficile, creerei la mia versione di cout
, forse chiamata mycout
che può essere definita in fase di compilazione o di runtime (a seconda di ciò che voglio fare).
Una soluzione semplice può essere:
#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 la versione cout potrebbe essere:
typedef std::cout mycout;
Una versione di runtime è un po 'più di lavoro ma facilmente realizzabile.
Altri suggerimenti
Shane, grazie mille per il tuo aiuto. Ecco la mia implementazione di lavoro finale.
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);
Ho modificato un po 'l'implementazione finale dell'OP, aggiungendo un costruttore e un distruttore. La creazione di un oggetto di questa classe sostituisce automaticamente il buffer di flusso in std :: cout
e quando l'oggetto esce dall'ambito, viene ripristinato il buffer di flusso originale. 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;
};
Per utilizzare il buffer di flusso in un file MEX, semplicemente:
mxstreambuf mout;
std::cout << "Hello World!\n";
... e non preoccuparti di dimenticare nulla.
cout
è un flusso di output di caratteri particolare. Se si desidera un cout
che scrive in un file, utilizzare un < code> fstream , in particolare un ofstream
. Hanno la stessa interfaccia fornita da cout
. Inoltre, se vuoi prendere il loro buffer (con rdbuf
) puoi.