MATLAB mexファイルのcoutを置き換えるためにstringbufを正しくオーバーロードする
-
04-07-2019 - |
質問
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
を使用して)バッファーを取得する場合は、次の操作を実行できます。