MathWorks currently doesn't allow you to use cout from a mex file when the MATLAB desktop is open because they have redirected stdout. Their current workaround is providing a function, mexPrintf, that they request you use instead. After googling around a bit, I think that it's possible to extend the std::stringbuf class to do what I need. Here's what I have so far. Is this robust enough, or are there other methods I need to overload or a better way to do this? (Looking for portability in a general UNIX environment and the ability to use std::cout as normal if this code is not linked against a mex executable)
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());
-
cout
is a particular character output stream. If you want acout
that writes to a file, use anfstream
, particularly anofstream
. They have the same interface thatcout
provides. Additionally, if you want to grab their buffer (withrdbuf
) you can.From Max Lybbert -
You don't really want to overload std::stringbuf, you want to overload std::streambuf or std::basic_streambuf (if you want to support multiple character types), also you need to override the overflow method as well.
But I also think you need to rethink your solution to your problem.
cout is just a ostream, so if all classes / functions takes a ostream then you can pass in anything you like. e.g. cout, ofstream, etc
If that's too hard then I would create my own version of cout, maybe called mycout that can be defined at either compiler time or runtime time (depending on what you want to do).
A simple solution may be:
#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;
And the cout version could just be:
typedef std::cout mycout;
A runtime version is a bit more work but easily doable.
From Shane Powell -
Shane, thanks very much for your help. Here's my final working implementation.
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; }
...
mstream mout; std::streambuf outbuf = std::cout.rdbuf(&mout);
...
std::cout.rdbuf(outbuf);
0 comments:
Post a Comment