Surcharger correctement un stringbuf pour remplacer cout dans un fichier MATLAB mex
-
04-07-2019 - |
Question
MathWorks ne vous permet actuellement pas d'utiliser cout
à partir d'un fichier mex lorsque le bureau MATLAB est ouvert car ils ont redirigé la sortie standard. Leur solution actuelle fournit une fonction, mexPrintf, qu'ils vous demandent d'utiliser à la place . Après avoir googlé un peu, je pense qu'il est possible d'étendre la classe std :: stringbuf
pour faire ce dont j'ai besoin. Voici ce que j'ai jusqu'à présent. Est-ce assez robuste ou y a-t-il d'autres méthodes dont j'ai besoin pour surcharger ou une meilleure façon de le faire? (Vous recherchez une portabilité dans un environnement UNIX général et la possibilité d'utiliser std :: cout
normalement si ce code n'est pas lié à un exécutable 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());
La solution
Vous ne voulez pas vraiment surcharger std :: stringbuf
, vous voulez surcharger std :: streambuf
ou std :: basic_streambuf
(si vous souhaitez prendre en charge plusieurs types de caractères), vous devez également redéfinir la méthode de débordement.
Mais je pense aussi que vous devez repenser votre solution à votre problème.
cout
est juste un ostream
, donc si toutes les classes / fonctions prennent un ostream
, vous pouvez alors passer tout ce que vous voulez. par exemple. cout
, du courant
, etc.
Si c'est trop difficile, je créerais ma propre version de cout
, appelée peut-être mycout
, qui peut être définie au moment du compilateur ou de l'exécution (selon ce que vous voulez). vouloir faire).
Une solution simple peut être:
#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;
Et la version du cout pourrait bien être:
typedef std::cout mycout;
Une version d'exécution représente un peu plus de travail mais est facilement réalisable.
Autres conseils
Shane, merci beaucoup pour votre aide. Voici ma dernière implémentation fonctionnelle.
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);
J'ai légèrement modifié l'implémentation finale du PO en ajoutant un constructeur et un destructeur. La création d'un objet de cette classe remplace automatiquement le tampon de flux dans std :: cout
et lorsque l'objet disparaît, le tampon de flux d'origine est restauré. 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;
};
Pour utiliser le tampon de flux dans un fichier MEX, simplement:
mxstreambuf mout;
std::cout << "Hello World!\n";
... et ne vous inquiétez pas pour rien oublier.
cout
est un flux de sortie de caractère particulier. Si vous voulez un cout
qui écrit dans un fichier, utilisez un < code> fstream , en particulier un ofstream
. Ils ont la même interface que cout
fournit. De plus, si vous voulez récupérer leur tampon (avec rdbuf
), vous pouvez.