正确地重载了一个stringbuf来替换MATLAB mex文件中的cout
-
04-07-2019 - |
题
当MATLAB桌面打开时,MathWorks目前不允许您使用mex文件中的 cout
,因为他们已重定向stdout。他们目前的解决方法是提供一个功能, 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
),你可以。