C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

streams and FILE* interoperability

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
sb
Guest





PostPosted: Tue Feb 17, 2004 11:40 am    Post subject: streams and FILE* interoperability Reply with quote



I think streams are nice, but what do you do when you have to write to
or, even worse, read from a FILE*, for example a UNIX stream?

C++ streams can not be created from FILE*'s or have them attached.

Today, a C++ programmer has to decide beforehand whether he wants to
use C or C++ I/O. Suppose you choose C++ streams and write all of the
"operator>>" code for your objects. If you later decide to read the
same objects from a UNIX pipe, you'll have to rewrite and re-debug
much of that code.

Since C++ was aiming for seamless interoperability with C, wouldn't it
have been easier to make its file stream a shallow wrapper around
FILE*? It already has the necessary buffering functionality. Or at
least specialize the character streams to be such bufferless wrappers
around FILE* ?

On a more positive note, I haven't used them yet, but it looks like
STLport provides such shallow stream wrappers as an option.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jeff Greif
Guest





PostPosted: Tue Feb 17, 2004 5:17 pm    Post subject: Re: streams and FILE* interoperability Reply with quote



You can build a custom streambuf based ultimately on FILE* and wrap your
istream or ostream around that. Some library implementations support this
directly, as an extension, or make it very easy.

For example, in the Microsoft Visual C++ 2003 library, basic_filebuf::open
is documented to call fopen. It would not be hard to provide a
specialization or similar implementation that added an open method taking a
FILE* argument. Then you could provide an specialization of fstream to use
that buffer.

Jeff

<spam_bait101 (AT) yahoo (DOT) com> wrote

Quote:
I think streams are nice, but what do you do when you have to write to
or, even worse, read from a FILE*, for example a UNIX stream?

C++ streams can not be created from FILE*'s or have them attached.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maciej Sobczak
Guest





PostPosted: Wed Feb 18, 2004 1:28 am    Post subject: Re: streams and FILE* interoperability Reply with quote



Hi,

sb wrote:

Quote:
Today, a C++ programmer has to decide beforehand whether he wants to
use C or C++ I/O. Suppose you choose C++ streams and write all of the
"operator>>" code for your objects. If you later decide to read the
same objects from a UNIX pipe, you'll have to rewrite and re-debug
much of that code.

No. IOStream are about code reuse. You do not have to rewrite anything.
The usual solution in such cases is to write (or get from someone) a
streambuf class wrapped around the new "device". Whether it is socket,
pipe or whatever else, the rules are similar.

The important thing is that all your operator>> stuff remains untouched,
because it operates on istream and ostream classes. The part that
changes between devices is the streambuf, which is a replaceable
component of the (i/o)stream object. In other words, your operators can
operate on any stream you give them - they are not aware of what is
inside (what device is actually used at the transport layer).

I think you can Google for ready to use solution - I'm sure somebody
else 's already done it.
You can see how it can be done in the case of sockets on my web-page.
Look around for sockets.zip. It should be quite easy to change it to
operate on pipes.

I also recommend the book by Angelika Langer and Klaus Kreft about
IOStream library, where various "hows and whys" are thoroughly explained.


As a side note: you ask why there is no seamless integration between
IOStreams and FILE*s. You may ask the same question about string library
in C++ vs. strxxx functions in C. :)

--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jonathan Turkanis
Guest





PostPosted: Wed Feb 18, 2004 12:06 pm    Post subject: Re: streams and FILE* interoperability Reply with quote

"sb" <spam_bait101 (AT) yahoo (DOT) com> wrote

Quote:
I think streams are nice, but what do you do when you have to write
to
or, even worse, read from a FILE*, for example a UNIX stream?

C++ streams can not be created from FILE*'s or have them attached.

Today, a C++ programmer has to decide beforehand whether he wants to
use C or C++ I/O. Suppose you choose C++ streams and write all of
the
"operator>>" code for your objects. If you later decide to read the
same objects from a UNIX pipe, you'll have to rewrite and re-debug
much of that code.


You might be interested in Nicolai Jossutis's fdstream classes,
implementing standard stream and stream buffers based on file
descriptors, for use on Windows or Unix.

http://www.josuttis.com/cppcode/fdstream.html

Jonathan



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Wed Feb 18, 2004 10:57 pm    Post subject: Re: streams and FILE* interoperability Reply with quote

In message <c0ti5g$smr$1 (AT) atlantis (DOT) news.tpi.pl>, Maciej Sobczak
<no.spam (AT) no (DOT) spam.com> writes
Quote:
Hi,

sb wrote:

Today, a C++ programmer has to decide beforehand whether he wants to
use C or C++ I/O. Suppose you choose C++ streams and write all of the
"operator>>" code for your objects. If you later decide to read the
same objects from a UNIX pipe, you'll have to rewrite and re-debug
much of that code.

No. IOStream are about code reuse. You do not have to rewrite anything.
The usual solution in such cases is to write (or get from someone) a
streambuf class wrapped around the new "device". Whether it is socket,
pipe or whatever else, the rules are similar.

Agreed, but I think we should consider providing such a facility for a
FILE objects in the Standard C++ Library.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maciej Sobczak
Guest





PostPosted: Fri Feb 20, 2004 1:03 am    Post subject: Re: streams and FILE* interoperability Reply with quote

Hi,

Francis Glassborow wrote:

Quote:
No. IOStream are about code reuse. You do not have to rewrite anything.
The usual solution in such cases is to write (or get from someone) a
streambuf class wrapped around the new "device". Whether it is socket,
pipe or whatever else, the rules are similar.

Agreed, but I think we should consider providing such a facility for a
FILE objects in the Standard C++ Library.

I'd rather see a *generic* (read: policy- or traits-based) facility for
this. I agree that there is a need to interface with C code (in
particular), and there may be a need to wrap a stream around a FILE
object, but a similar need may arouse in case of raw API objects
(descriptors on Unices, handles on Windows, etc.). Most of the platforms
present a similar concepts when it comes to files
(open/close/read/write/etc.), which can be stripped down to universal
pair read/write, if we assume that we have an object that is already
open and configured for transmission (this is the only motivation for
interfacing, I think).
In other words, I can imagine something like this:

// a sketch only, not checked
template <class F>
struct file_traits
{
size_t read(F &f, void *buf, size_t n);
size_t write(F &f, const void *buf, size_t n);

// probably some typedefs, etc.
// ...
};

template <
class charT,
class F,
class ctraits = char_traits class ftraits = file_traits<F>
Quote:

class generic_file_streambuf

: public basic_streambuf<charT, ctraits>
{
public:
generic_file_streambuf(F &f);
// ...

private:
F &f_;
};

The Standard would only require that implementation provides
specialization for file_traits<FILE*>, leaving the door open for library
extensions that may support other file-like objects, even if they are
platform dependent.

The above idea is based on the assumption that the architecture of
stream buffer is roughly similar in all cases, where read/write
primitives can be reasonably defined. They can be even defined exactly
to fit the FILE objects, imposing some additional work on those who wish
to interface with some strange devices. There is still a lot of room for
(partial) specializations.

--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jonathan Turkanis
Guest





PostPosted: Fri Feb 20, 2004 3:04 pm    Post subject: Re: streams and FILE* interoperability Reply with quote


"Maciej Sobczak" <no.spam (AT) no (DOT) spam.com> wrote:

Quote:
I'd rather see a *generic* (read: policy- or traits-based) facility
for
this. I agree that there is a need to interface with C code (in
snip
In other words, I can imagine something like this:

// a sketch only, not checked
template <class F
struct file_traits
{
size_t read(F &f, void *buf, size_t n);
size_t write(F &f, const void *buf, size_t n);

// probably some typedefs, etc.
// ...
};

template
class charT,
class F,
class ctraits = char_traits class ftraits = file_traits<F

class generic_file_streambuf
: public basic_streambuf {
public:
generic_file_streambuf(F &f);
// ...

private:
F &f_;
};

The Standard would only require that implementation provides
specialization for file_traits library
extensions that may support other file-like objects, even if they
are
platform dependent.

I've written a complete library along these line (submitted to Boost).
It provides a toolkit for defining new streams and stream buffers
based on policies with interfaces similar to the above. (It also
allows for adding chains of filters).

I found it more general to eliminate the 'F' in your examples, and
incorporate it as state into the policies. The basic concepts are
those of a Source (readable stream of characters) and a Sink (writable
stream of characters), together with two common refinements of Source
and Sink, supporting read-write and random-access stream.

The policies are expected to have some member typedefs, so only one
template parameter would be necessary in the above example. A
read-write streambuf template would look something like this:

template<typename Resource>
struct generic_streambuf {
typedef typename Resource::char_type char_type;
typedef typename Resource::traits_type traits_type;
// Other typedefs

generic_streambuf(const Resource& rsrc, openmode m =
.... );
void open(const Resource& rsrc, openmode m = );
bool is_open const();
void close();
};

(The names are different in my library.)

Jonathan



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Richard Smith
Guest





PostPosted: Sat Feb 21, 2004 4:16 am    Post subject: Re: streams and FILE* interoperability Reply with quote

Jeff Greif wrote:
Quote:
You can build a custom streambuf based ultimately on FILE* and wrap your
istream or ostream around that.

In priciple you can do this; in practice it's not quite that easy.
C's FILE* stream mechanism has its own buffering mechanism based on a
single buffer that is either used for reading _or_ for writing. By
contrast C++'s iostreams have two buffers, one for reading and one
for writing. This allows C++ iostreams to more flexible in their
usage than C's FILE* streams.

If the custom streambuf is to be implemented on top of a FILE*, the
FILE*'s own buffering must be disabled (unless the FILE* stream
happens to provide an extension to make it work). This is perfectly
possible: a simple call to

std::setbuf( stream, NULL );

will achieve this. However, the setbuf function "may be used only
after the stream pointed to by stream has been associated with an open
file and before any other operation is performed on the stream" [C90
7.9.5.6].

If the streambuf is responsible for creating the FILE* stream itself,
there's no problem with this. But if you have a constructor accepting
a FILE* stream, this imposes a very strict limitation: If the only
place that the FILE* stream could have come from was call to fopen(),
you may as well get the streambuf constructor to do this.

Presumably, you intend to use some non-standard way of creating a
FILE*; perhaps something like POSIX's fdopen which converts a
low-level file descriptor to a FILE* buffer. But if you're going to
do that, I would have thought you'd be much better implementing the
streambuf directly on top of the low-level file descriptor, rather
than using the intermediate FILE*.

The three main advantages of a FILE* over a file descriptor are (i) a
standard interface, (ii) formatting, (iii) buffering. As you've
disabled buffering, are using iostreams for the formatting and
assuming some non-standard interface anyway (e.g. the fdopen
function), you've lost all three advantages: you might as
avoid the extra indirection and use the low-level construct directly.


Quote:
For example, in the Microsoft Visual C++ 2003 library, basic_filebuf::open
is documented to call fopen.

The Standard says that basic_filebuf::open behaves "'as if' by calling
std::fopen" [27.8.1.3/2]. To me, this means that it behaves
indistinguishably from how it would have behaved had it called
std::fopen. In view of this, it's largely irrelevant whether or not
it actually calls std::fopen.

--
Richard Smith

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Sat Feb 21, 2004 4:12 pm    Post subject: Re: streams and FILE* interoperability Reply with quote

In message <1a0929fa.0402200625.367e98a5 (AT) posting (DOT) google.com>, Richard
Smith <richard (AT) ex-parrot (DOT) com> writes
Quote:
The three main advantages of a FILE* over a file descriptor are (i) a
standard interface, (ii) formatting, (iii) buffering. As you've
disabled buffering, are using iostreams for the formatting and
assuming some non-standard interface anyway (e.g. the fdopen
function), you've lost all three advantages: you might as
avoid the extra indirection and use the low-level construct directly.

I suspect the problem is to have a way that given a FILE* (perhaps as a
return from a third party library) create an fstream to access the same
file (whose name you might not know). There is also the reverse problem,
given some kind of fstream create a suitable FILE whose address can be
passed to a function needing a FILE*. Yes I know there are all kinds of
details that need tackling which is, perhaps, why the Standard C++
Library might provide the tools.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.