MATLAB mexファイルのcoutを置き換えるためにstringbufを正しくオーバーロードする

StackOverflow https://stackoverflow.com/questions/243696

質問

MathWorksは現在、stdoutをリダイレクトしているため、MATLABデスクトップが開いているときにmexファイルから cout を使用することを許可していません。現在の回避策は、 mexPrintf関数を提供することです。 。少し探し回った後、 std :: stringbuf クラスを拡張して必要なことを行うことができると思います。ここに私がこれまで持っているものがあります。これは十分に堅牢ですか、それとも私がオーバーロードする必要がある他の方法またはこれを行うためのより良い方法がありますか? (一般的なUNIX環境での移植性と、このコードがmex実行可能ファイルにリンクされていない場合、通常どおり std :: cout を使用する機能を探しています)

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());    
役に立ちましたか?

解決

std :: stringbuf をオーバーロードしたくない、 std :: streambuf または std :: basic_streambuf をオーバーロードしたい(複数の文字タイプをサポートする場合)、オーバーフローメソッドもオーバーライドする必要があります。

しかし、問題の解決策を再考する必要があると思います。

cout は単なる ostream であるため、すべてのクラス/関数が ostream を取る場合は、任意の値を渡すことができます。例えば cout ofstream など

それが難しすぎる場合は、 cout の独自バージョンを作成します。これは、 mycout と呼ばれ、コンパイラー時間またはランタイム時に定義できますしたい)。

簡単な解決策は次のとおりです。

#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;

そしてcoutバージョンは次のようになります:

typedef std::cout mycout;

ランタイムバージョンはもう少し手間がかかりますが、簡単に実行できます。

他のヒント

シェーン、助けてくれてありがとう。これが私の最終的な実装です。

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

OPの最終実装を少し変更し、コンストラクタとデストラクタを追加しました。このクラスのオブジェクトを作成すると、 std :: cout のストリームバッファーが自動的に置き換えられ、オブジェクトがスコープ外になると、元のストリームバッファーが復元されます。 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;
};

MEXファイルでストリームバッファーを使用するには、次のようにします。

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

...そして、何も忘れないでください。

cout は特定の文字出力ストリームです。ファイルに書き込む cout が必要な場合は、 < code> fstream 、特に ofstream 。これらには、 cout が提供するものと同じインターフェースがあります。また、( rdbuf を使用して)バッファーを取得する場合は、次の操作を実行できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top