redefining cout (for using printf/mexprintf)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • uli

    redefining cout (for using printf/mexprintf)

    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.cp p) 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
    --
    For reply remove NOSPAM_ from email-adress



  • Michiel Salters

    #2
    Re: redefining cout (for using printf/mexprintf)

    "uli" <NOSPAM_uvb@nur fuerspam.de> wrote in message news:<c62sdn$p8 q$1@newssrv.muc .infineon.com>. ..[color=blue]
    > 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.cp p) so that it makes use of printf() instead . Could someone
    > give me some hints or links to information how I could manage this?[/color]

    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::ofstream, 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::rd buf(std::stream buf*).

    Regards,
    Michiel Salters

    Comment

    • Dietmar Kuehl

      #3
      Re: redefining cout (for using printf/mexprintf)

      "uli" <NOSPAM_uvb@nur fuerspam.de> wrote:[color=blue]
      > To solve this I want to redefine std::cout (within a header of my individual
      > MEXinterface.cp p) so that it makes use of printf() instead . Could someone
      > give me some hints or links to information how I could manage this?[/color]

      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).
      [color=blue]
      > I know that it must be tricky since cout prints stream?! So I need to
      > transform the stream in strings??[/color]

      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.
      --
      <mailto:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
      <http://www.contendix.c om> - Software Development & Consulting

      Comment

      • uli

        #4
        Re: redefining cout (for using printf/mexprintf)

        "Dietmar Kuehl" <dietmar_kuehl@ yahoo.com> wrote in message[color=blue]
        > "uli" <NOSPAM_uvb@nur fuerspam.de> wrote:[color=green]
        > > To solve this I want to redefine std::cout (within a header of my[/color][/color]
        individual[color=blue][color=green]
        > > MEXinterface.cp p) so that it makes use of printf() instead . Could[/color][/color]
        someone[color=blue][color=green]
        > > give me some hints or links to information how I could manage this?[/color]
        >
        > 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).
        >[color=green]
        > > I know that it must be tricky since cout prints stream?! So I need to
        > > transform the stream in strings??[/color]
        >
        > 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.[/color]


        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::out);
        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


        Comment

        • Dietmar Kuehl

          #5
          Re: redefining cout (for using printf/mexprintf)

          uli wrote:[color=blue]
          > Ok, I tried to figure it out with my STL literature.[/color]

          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.
          [color=blue]
          > But for redirecting it to another function how can I change the streambuf*
          > to 'string' then, like:[/color]

          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_st r());
          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_ty pe c) {
          if (!traits_type:: eq_int_type(c, traits_type::eo f()) {
          *pptr() = traits_type::to _char_type(c);
          pbump(1);
          }
          return sync() != -1? traits_type::no t_eof(c): traits_type::eo f();
          }
          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.co m/> to locate past articles)
          --
          <mailto:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
          <http://www.contendix.c om> - Software Development & Consulting

          Comment

          • Jack Walker

            #6
            Re: redefining cout (for using printf/mexprintf)

            "uli" <NOSPAM_uvb@nur fuerspam.de> wrote in message news:<c63l8a$4r c$1@newssrv.muc .infineon.com>. ..[color=blue]
            > "Dietmar Kuehl" <dietmar_kuehl@ yahoo.com> wrote in message[color=green]
            > > "uli" <NOSPAM_uvb@nur fuerspam.de> wrote:[color=darkred]
            > > > To solve this I want to redefine std::cout (within a header of my[/color][/color]
            > individual[color=green][color=darkred]
            > > > MEXinterface.cp p) so that it makes use of printf() instead . Could[/color][/color]
            > someone[color=green][color=darkred]
            > > > give me some hints or links to information how I could manage this?[/color]
            > >
            > > 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).
            > >[color=darkred]
            > > > I know that it must be tricky since cout prints stream?! So I need to
            > > > transform the stream in strings??[/color]
            > >
            > > 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.[/color]
            >
            >
            > 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::out);
            > 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!
            >[/color]
            Try stringstream for in core formatted output:

            ostringstream sout ;

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

            ..
            ..
            ..


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



            Jack Walker
            [color=blue]
            >
            > thanx, once again!
            > uli[/color]

            Comment

            Working...