tags:

views:

291

answers:

5

Is it possible in C/C++ to create my own custom stream of type FILE (stdio.h) that can be used with fputs() for example ?

+5  A: 

No it isn't. FILE is what is known as an opaque type - it doesn't have anything you can customise.

anon
Then how come windows can handle files on disk, files on the network, virtual files, ...? Some aspect must be customizeable.
xtofl
Name one then. The FILE type has no members available to the application programmer.
anon
@xtofl: because FILE* on Windows maps to the HANDLE returned by CreateFile. FILE* doesn't do the "customization"
MSalters
A: 

It is possible. But you should link your application with your version of fputs(), etc instead of those coming with the standard libraries. Most compilers link to the standard IO libraries by default. You have to figure out how to get around that.

Vijay Mathew
He doesn't want to re-write fputs(), he wants to specialise FILE. Or at least that's my reading.
anon
if I define my own fputs(), any call of fputs() will go through my fputs.
Soubok
+1  A: 

There is no standard way with the FILE interface. Note that C++ code usually should use IOStream for IO, with the IOStream interface, writing a custom streambuf is the solution to your problem.

If you can drop standard conformance, look at the documentation of your implementation.

  • POSIX has a popen() function which create a FILE* reading from the output or writing to the input of a process;

  • POSIX has a fdopen() which is able to create a FILE* from a file descriptor;

  • At least for the GNU libc used by Linux, there is a possibility of defining custom C stream (see the "Programming your awn custom streams" section in the info documentation).

AProgrammer
How does popen(0 address the issue?
anon
We don't know enough about the problem to be sure. We just know that he has to pass a FILE* to an API. Organizing its program in two or more processes could be a solution (spawning a process which does a popen() and then call the API with the result for example).
AProgrammer
I see, thanks for the suggestion, but I cannot do that. The API I use has also a context as argument and it could be very difficult to apply this solution.
Soubok
@AProgrammer. In that case, popen() is a possible answer to almost every question posted on SO - not very useful, I feel.
anon
@Neil, you are reading more in my suggestion of popen() than I intended. It was meant to be an example of system specific stuff which are available. I put it before the GNU libc custom stream just because being POSIX is more standard. I've reformulated that entry hoping to be clearer and added fdopen() to be a little more complete.
AProgrammer
A: 

If you are compiling with the GNU C library you could use fmemopen(3):

fmemopen, open_memstream, open_wmemstream - open memory as stream

Inshallah
+1  A: 

If your "custom stream" isn't something you can represent with a file descriptor or file handle, then you're out of luck. The FILE type is implementation-defined, so there's no standard way to associate other things with one.

If you can get a C file descriptor for whatever it is you're trying to write to, then you can call fdopen on it to turn it into a FILE*. It's not standard C or C++, but it's provided by Posix. On Windows, it's spelled _fdopen.

If you're using Windows and you have a HANDLE, then you can use _open_osfhandle to associate a file descriptor with it, and then use _fdopen from there.

Are you really tied to fputs? If not, then replace it with use of a C++ IOStream. Then you can provide your own descendant of std::basic_streambuf, wrap it in a std::ostream, and use standard C++ I/O on it.

Rob Kennedy
Thanks a lot, this works: CreatePipe() + _open_osfhandle() + fdopen()
Soubok