8

MathWorks 目前不允许您cout在 MATLAB 桌面打开时使用 mex 文件,因为它们已重定向标准输出。他们当前的解决方法是提供一个函数mexPrintf,他们要求您使用它。在谷歌搜索了一下之后,我认为可以扩展std::stringbuf课程来做我需要的事情。这是我到目前为止所拥有的。这是否足够强大,还是我需要重载其他方法或更好的方法来做到这一点?std::cout(如果此代码未链接到 mex 可执行文件,则在一般 UNIX 环境中寻找可移植性以及正常使用的能力)

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

4 回答 4

9

你真的不想重载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;

运行时版本需要更多工作,但很容易实现。

于 2008-10-28T19:46:45.123 回答
9

谢恩,非常感谢你的帮助。这是我的最终工作实现。

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); 
于 2008-10-30T01:28:13.467 回答
1

我稍微改变了 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";

......不要担心忘记任何东西。

于 2016-12-22T05:42:26.110 回答
0

cout是一个特定的字符输出流。如果您想要 acout写入文件,请使用 a fstream,尤其是ofstream. 它们具有cout提供的相同接口。此外,如果您想获取他们的缓冲区(使用rdbuf),您可以。

于 2008-10-28T18:19:11.370 回答