Korrekt über Laden ein stringbuf cout in einer MATLAB mex-Datei zu ersetzen
-
04-07-2019 - |
Frage
MathWorks ist zur Zeit nicht zulassen, dass Sie cout
von einer mex-Datei verwenden, wenn die MATLAB-Desktop geöffnet ist, weil sie stdout umgeleitet haben. Ihre aktuelle Problemumgehung bietet eine Funktion, mexPrintf, dass sie fordern Sie stattdessen verwenden . um ein bisschen nach googeln, denke ich, dass es möglich ist, die std::stringbuf
Klasse zu erweitern zu tun, was ich brauche. Hier ist, was ich bisher haben. Ist das robust genug ist, oder gibt es andere Methoden, die ich brauche, um eine Überlastung oder ein besserer Weg, dies zu tun? (Suche nach Portabilität in einer allgemeinen UNIX-Umgebung und die Fähigkeit std::cout
als normal zu verwenden, wenn dieser Code nicht gegen einen mex ausführbaren verknüpft ist)
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());
Lösung
Sie wollen nicht wirklich std::stringbuf
zu überlasten, wollen Sie std::streambuf
oder std::basic_streambuf
zu überlasten (falls Sie mehrere Zeichentypen unterstützen wollen), auch müssen Sie auch die Überlauf-Methode überschreiben.
Aber ich denke auch Sie Ihre Lösung für Ihr Problem zu überdenken müssen.
cout
ist nur ein ostream
, also wenn alle Klassen / Funktionen ein ostream
nimmt, dann können Sie in alles, was Sie gerne weitergeben. z.B. cout
, ofstream
, etc
Wenn das zu hart ist, dann würde ich meine eigene Version von cout
schaffen, vielleicht genannt mycout
, die an jedem Compiler oder Laufzeit Zeit definiert werden kann (je nachdem, was Sie tun wollen).
Eine einfache Lösung kann sein:
#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;
Und die cout Version konnte nur sein:
typedef std::cout mycout;
Eine Runtime-Version ist ein bisschen mehr Arbeit, aber leicht machbar.
Andere Tipps
Shane, vielen Dank für Ihre Hilfe. Hier ist meine letzte Arbeits Umsetzung.
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);
Ich habe die OP der endgültige Umsetzung ein wenig verändert, einen Konstruktor und Destruktor hinzufügen. ein Objekt dieser Klasse erstellen ersetzt automatisch den Strompuffer in std::cout
, und wenn das Objekt den Bereich verlässt, wird der ursprüngliche Strompuffer wiederhergestellt. RAH!
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;
};
Um den Strompuffer in einer MEX-Datei zu verwenden, einfach:
mxstreambuf mout;
std::cout << "Hello World!\n";
... und keine Sorge über alles zu vergessen.
cout
ist ein bestimmtes Zeichen Ausgabestrom. Wenn Sie eine cout
möchten, die in eine Datei schreibt, verwenden Sie einen fstream
, insbesondere ein ofstream
. Sie haben die gleiche Schnittstelle, die cout
zur Verfügung stellt. Außerdem, wenn Sie wollen, dass ihre Puffer (mit rdbuf
) greifen Sie können.