2008-10-28 6 views
8

Actuellement, MathWorks ne vous permet pas d'utiliser cout depuis un fichier mex lorsque le bureau MATLAB est ouvert car il a redirigé stdout. Leur solution de contournement actuelle fournit une fonction, mexPrintf, that they request you use instead. Après un peu de recherche, 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'ici. Est-ce assez robuste, ou existe-t-il d'autres méthodes que je devrais surcharger ou une meilleure façon de le faire? (Recherche de la portabilité dans un environnement UNIX général et la possibilité d'utiliser std :: Cout comme normal si ce code est pas lié à un exécutable MEX)Surcharger correctement un stringbuf pour remplacer cout dans un fichier mex MATLAB

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());  

Répondre

9

Vous ne voulez pas vraiment surcharger std :: stringbuf, vous voulez surcharger std :: streambuf ou std :: basic_streambuf (si vous voulez supporter plusieurs types de caractères), vous devez également surcharger la méthode overflow bien.

Mais je pense aussi que vous devez repenser votre solution à votre problème. Cout est juste un ostream, donc si toutes les classes/fonctions prend un ostream alors vous pouvez passer dans tout ce que vous aimez. par exemple. cout, ofstream, etc

Si c'est trop difficile alors je créerais ma propre version de cout, peut-être appelée mycout qui peut être définie au moment du compilateur ou de l'exécution (en fonction de ce que vous voulez 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 Cout pourrait juste être:

typedef std::cout mycout; 

Une version d'exécution est un peu plus de travail, mais facilement réalisable.

0

cout est un flux de sortie de caractère particulier. Si vous voulez un cout qui écrit dans un fichier, utilisez un fstream, en particulier un ofstream. Ils ont la même interface que cout fournit. En outre, si vous voulez récupérer leur tampon (avec rdbuf) vous pouvez.

9

Shane, merci beaucoup pour votre aide. Voici ma dernière mise en œuvre de travail.

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); 
+0

La restauration du tampon de flux std s'est avérée très importante. Sans le faire, ma fonction mex semblait avoir un problème de mémoire et s'est écrasée matlab lors de la re * compilation *. –

1

J'ai changé la mise en œuvre finale de l'OP un peu, en ajoutant un constructeur et destructeur. La création d'un objet de cette classe remplace automatiquement le tampon de flux dans std::cout et lorsque l'objet est hors de portée, 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 MEX-file, tout simplement:

mxstreambuf mout; 
std::cout << "Hello World!\n"; 

... et ne vous inquiétez pas oublier quoi que ce soit.

Questions connexes