2008-10-28 37 views
8

MathWorks hiện không cho phép bạn sử dụng cout từ tệp mex khi máy tính để bàn MATLAB mở vì chúng đã chuyển hướng xuất chuẩn. Cách giải quyết hiện tại của họ là cung cấp hàm, mexPrintf, that they request you use instead. Sau khi googling xung quanh một chút, tôi nghĩ rằng nó có thể mở rộng std :: stringbuf lớp để làm những gì tôi cần. Đây là những gì tôi có cho đến nay. Đây có phải là đủ mạnh mẽ, hoặc có những phương pháp khác tôi cần phải quá tải hoặc một cách tốt hơn để làm điều này? (Looking for di động trong một môi trường UNIX nói chung và khả năng sử dụng std :: cout như bình thường nếu mã này không được liên kết với một mex thực thi)Chính xác quá tải chuỗi chuỗi để thay thế cout trong tệp mex MATLAB

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

Trả lời

9

Bạn không thực sự muốn quá tải std :: stringbuf, bạn muốn quá tải std :: streambuf hoặc std :: basic_streambuf (nếu bạn muốn hỗ trợ nhiều loại ký tự), bạn cũng cần ghi đè phương thức tràn tốt.

Nhưng tôi cũng nghĩ rằng bạn cần phải suy nghĩ lại giải pháp cho vấn đề của mình.

cout chỉ là một ostream, vì vậy nếu tất cả các lớp/chức năng có một ostream thì bạn có thể vượt qua bất cứ điều gì bạn thích. ví dụ. Nếu đó là quá khó thì tôi sẽ tạo ra phiên bản của riêng tôi của cout, có thể được gọi là mycout có thể được xác định tại một trong hai thời gian trình biên dịch hoặc thời gian chạy (tùy thuộc vào những gì bạn muốn làm). Quay lại đầu trang ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Một giải pháp đơn giản có thể là:

#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; 

Và phiên bản cout chỉ có thể là:

typedef std::cout mycout; 

Một phiên bản runtime là công việc nhiều hơn một chút nhưng dễ dàng thực hiện được.

0

cout là một dòng đầu ra nhân vật cụ thể. Nếu bạn muốn một số cout ghi vào một tệp, hãy sử dụng số fstream, đặc biệt là ofstream. Họ có cùng giao diện mà cout cung cấp. Ngoài ra, nếu bạn muốn lấy bộ đệm của chúng (với rdbuf) bạn có thể.

9

Shane, cảm ơn rất nhiều vì sự giúp đỡ của bạn. Đây là lần thực hiện cuối cùng của tôi.

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); 
+0

Khôi phục bộ đệm luồng std được chứng minh là rất quan trọng. Mà không làm như vậy chức năng mex của tôi dường như nhận được một số loại vấn đề bộ nhớ và bị rơi matlab khi tái biên dịch *. –

1

Tôi đã thay đổi thực hiện cuối cùng của OP một chút, thêm một constructor và destructor. Tạo một đối tượng của lớp này sẽ tự động thay thế bộ đệm luồng trong std::cout và khi đối tượng nằm ngoài phạm vi, bộ đệm luồng ban đầu được khôi phục. 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; 
}; 

Để sử dụng bộ đệm dòng trong một MEX-file, chỉ cần:

mxstreambuf mout; 
std::cout << "Hello World!\n"; 

... và đừng lo lắng về việc quên bất cứ điều gì.

Các vấn đề liên quan