在MATLAB mex文件中正确地重载字符串uf以替换cout
Correctly over-loading a stringbuf to replace cout in a MATLAB mex file
MathWorks当前不允许在MATLAB桌面打开时使用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;
运行时版本需要更多的工作,但很容易实现。
Shane,非常感谢您的帮助。这是我的最后一个工作实现。
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
中的流缓冲区,当对象超出范围时,将恢复原始流缓冲区。赖!
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
写入文件,请使用fstream
,尤其是ofstream
。它们具有与cout
相同的接口。此外,如果你想获取他们的缓冲区(使用rdbuf
),你可以。