redefining cout (for using printf/mexprintf)

U

uli

Hi all!
I'm posting to both newsgroups, because it's actually a C++ problem but
could be that some of you using Matlab-&-MEX-&-C++ was struggling with the
same problem.

I'm trying to rewrite some Matlab routines in C++ for reusing them
identically in Matlab and some other simulation tools. For computational
algebra I want to use the Matrix Template Library (MTL,
http://www.osl.iu.edu/research/mtl/) which is written in C++ and therefore
makes use of std::cout.
I have to use the mexfunction-interface of Matlab to run C++ code within a
Matlab simulation. Since I'm writing my code with MSVC++ 6.0 and running
Matlab on Windows, together with MATLAB and MEX, I can't use "cout" but
"printf" ('cause of the MSWindows specific Matlab-Terminal).


However to come to my Problem now:
To solve this I want to redefine std::cout (within a header of my individual
MEXinterface.cpp) so that it makes use of printf() instead . Could someone
give me some hints or links to information how I could manage this?
I know that it must be tricky since cout prints stream?! So I need to
transform the stream in strings??
Perhaps as a last resort, if it can't be done, any "std::cout << ... "
should print a infomessage.

I know it's not a good way to redefine some functions of the std namespace.
I have never done something like this. But it seems to me to be the only way
out. I also just want to use this redefinition together with Matlab-&-MEX
and probably won't make much use of MTL specific printouts...


thanx a lot of for any kind of help!
regards,
uli
 
M

Michiel Salters

uli said:
Hi all!
I'm posting to both newsgroups, because it's actually a C++ problem but
could be that some of you using Matlab-&-MEX-&-C++ was struggling with the
same problem.

I'm trying to rewrite some Matlab routines in C++ for reusing them
identically in Matlab and some other simulation tools. For computational
algebra I want to use the Matrix Template Library (MTL,
http://www.osl.iu.edu/research/mtl/) which is written in C++ and therefore
makes use of std::cout.
I have to use the mexfunction-interface of Matlab to run C++ code within a
Matlab simulation. Since I'm writing my code with MSVC++ 6.0 and running
Matlab on Windows, together with MATLAB and MEX, I can't use "cout" but
"printf" ('cause of the MSWindows specific Matlab-Terminal).


However to come to my Problem now:
To solve this I want to redefine std::cout (within a header of my individual
MEXinterface.cpp) so that it makes use of printf() instead . Could someone
give me some hints or links to information how I could manage this?

Sure, it's not very complex. Inside std::cout, there is something called
a streambuf. The default streambuf is responsible for writing the
already formatted text to the console (formatting was done by the
std::cout object itself). If you want to send the text to a different
destination, you will have to replace the streambuf. E.g. if you
want to redirect std::cout to a file, open a std::eek:fstream, and swap
the streambufs. If you have another destination, derive your
custom sterambuf from std::streambuf and implement the applicable
virtual functions.
Pointer: std::stream::rdbuf(std::streambuf*).

Regards,
Michiel Salters
 
D

Dietmar Kuehl

uli said:
To solve this I want to redefine std::cout (within a header of my individual
MEXinterface.cpp) so that it makes use of printf() instead . Could someone
give me some hints or links to information how I could manage this?

You should not try to "redefine std::cout". What you can do is to replace
the stream buffer used by 'std::cout' with a stream buffer writing to a
new destination, eg. to 'printf()' (although the destinations of 'printf()
and 'std::cout' should actually be identical).
I know that it must be tricky since cout prints stream?! So I need to
transform the stream in strings??

Streams write the chars to stream buffers. These collect the chars in a
buffer which can then be easily handed to whatever function you want to
use. This is the way I would go, anyway.
 
U

uli

Dietmar Kuehl said:
You should not try to "redefine std::cout". What you can do is to replace
the stream buffer used by 'std::cout' with a stream buffer writing to a
new destination, eg. to 'printf()' (although the destinations of 'printf()
and 'std::cout' should actually be identical).


Streams write the chars to stream buffers. These collect the chars in a
buffer which can then be easily handed to whatever function you want to
use. This is the way I would go, anyway.


Ok, I tried to figure it out with my STL literature. But it seems, that I'am
not really good in C++!
I now know to redirect cout to a file with:
#include <fstream.h>
filebuf *pBuf = new filebuf;
pBuf->open("cout.txt", ios::eek:ut);
cout = pBuf;

// ... more code

delete cout.rdbuf();

But for redirecting it to another function how can I change the streambuf*
to 'string' then, like:
#include <iostream>
std::streambuf* str_buf = std::cout.rdbuf();
printf("%s", *str_buf); //<<< doesn't work of course!


thanx, once again!
uli
 
J

Jack Walker

uli said:
Ok, I tried to figure it out with my STL literature. But it seems, that I'am
not really good in C++!
I now know to redirect cout to a file with:
#include <fstream.h>
filebuf *pBuf = new filebuf;
pBuf->open("cout.txt", ios::eek:ut);
cout = pBuf;

// ... more code

delete cout.rdbuf();

But for redirecting it to another function how can I change the streambuf*
to 'string' then, like:
#include <iostream>
std::streambuf* str_buf = std::cout.rdbuf();
printf("%s", *str_buf); //<<< doesn't work of course!
Try stringstream for in core formatted output:

ostringstream sout ;

sout << "stuff to write out" << endl ;

..
..
..


mexprintf("%s", sout.c_str()) ;



Jack Walker
 
D

Dietmar Kuehl

uli said:
Ok, I tried to figure it out with my STL literature.

STL literature would not cover anything related to streams (with the
exception of the various stream iterators) since streams are not part
of the STL: the STL is a library which essentially became the
functional, algorithms, iterators, and containers library of the
standard C++ library. That is STL != standard C++ library.
But for redirecting it to another function how can I change the streambuf*
to 'string' then, like:

Well, this is not exactly what you probably want to do but you could
use a 'std::stringbuf' at first:

#include <iostream>
#include <sstream>
int main() {
std::streambuf* cout_sbuf = std::cout.rdbuf();
std::stringbuf sbuf;
std::cout.rdbuf(&sbuf);
// ...
printf("stream contents: %s\n", sbuf.str().c_str());
std::cout.rdbuf(cout_sbuf);
}

It is relatively important that you restore the original stream buffer
into the stream because after exiting 'main()' the standard stream
objects may be flushed (due to the behavior of the destructor of
'std::ios_base::Init'). Since the installed stream buffer is destructed
by then, this would result in a crash during program termination which
is generally not the best behavior and may even cause havoc on some of
the data which is not yet flushed.

However, I was actually not refering to installing one of the existing
stream buffers since these don't really do the right thing. You want
to create your own stream buffer by deriving from 'std::streambuf' and
overriding the 'overflow()' and 'sync()' methods. The tricky part in
your particular setup is that you apparently have two routes to write
output:
- you might use 'std::cout' to write output
- you might use the underlying mechanism directly to write output
In situations like this you get synchronization problems if you are
not careful and do buffering in the stream buffer. On the other hand,
using an unbuffered stream buffer is likely to cause a performance
problem. You might compromise on setting the 'unitbuf' flag which will
flush the stream after every insertion operation. Another alternative
is to terminate all uses of 'std::cout' with 'std::endl' or 'std::flush'
(the difference between these two is that the former adds a newline
prior to the flush; in general, I recommend against use of 'std::endl'
because it mixes two entirely separate issues but sometimes it just has
the right semantics...).

A simple stream buffer for your purpose would look something like this:

struct printfbuf: std::streambuf {
enum { s_size = 1024 };
printfbuf() { setp(m_buffer, m_buffer + s_size - 2); }
private:
int_type overflow(int_type c) {
if (!traits_type::eq_int_type(c, traits_type::eof()) {
*pptr() = traits_type::to_char_type(c);
pbump(1);
}
return sync() != -1? traits_type::not_eof(c): traits_type::eof();
}
int sync() {
*pptr() = 0;
printf(pbase());
setp(m_buffer, m_buffer + s_size - 2);
return 0;
}
char m_buffer[s_size];
};

This code is not tested (not even compiled) and I guess I forgot
something important. However, to find out more about implementing
stream buffers, you can have a look at various resources:
- Nicolai Josuttis' book "The C++ Standard Library" (Addison-Wesley)
describes this stuff (actually, I have translated/rewritten this
section)
- Angelika Langer and Klaus Kreft's book "C++ IOStreams and Locales"
(Addison-Wesley) covers this stuff in depth
- I have written loads of articles in newsgroup (use eg.
<http://group.google.com/> to locate past articles)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top