help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How do I pass a file pointer to my octfile?


From: John W. Eaton
Subject: How do I pass a file pointer to my octfile?
Date: Wed, 22 Sep 2010 20:37:59 -0400

On 22-Sep-2010, baba wrote:

| I am trying to pass a file id to my octfile function. In my octave script I
| do:
| 
| fid = fopen( filename, 'w');
| 
| then I would like to be able to call my oct function this way:
| 
| myOctFunction( fid, someDataToWrite);
| 
| >From code snippets I have read I can guess that my oct file should look
| something like:
| 
| DEFUN_DLD(fann_save_fd,args, , )
| {
|     const octave_base_value& rep = args(0).get_rep();
|     const FILE* fp = ((const FILE*)rep);
| 
| }
| 
| I am not sure what rep is ... I am guessing it is a generic pointer to the
| argument's content?
| Is that a proper way to do it?

No, the FID that you get from fopen is just an integer stored as a
double precision number.  Look at a function like fputs, defined in
src/file-io.cc:

  DEFUN (fputs, args, ,
    "-*- texinfo -*-\n\
  @deftypefn {Built-in Function} {} fputs (@var{fid}, @var{string})\n\
  Write a string to a file with no formatting.\n\
  \n\
  Return a non-negative number on success and EOF on error.\n\
  @seealso{scanf, sscanf, fread, fprintf, fgets, fscanf}\n\
  @end deftypefn")
  {
    static std::string who = "fputs";

    octave_value retval = -1;

    int nargin = args.length ();

    if (nargin == 2)
      {
        octave_stream os = octave_stream_list::lookup (args(0), who);

        if (! error_state)
          retval = os.puts (args(1), who);
      }
    else
      print_usage ();

    return retval;
  }

So you can convert a double precision file ID value to an
octave_stream object (assuming there is an open stream that
corresponds to that file ID).  From that, you can convert it to a
pointer to a std::ostream (or std::istream) object.  There is no
direct conversion from that to a C FILE pointer. -- the C++
std::{i,o,io}stream objects might not actually be based directly on C
FILE pointers.  For example, if you open a stream with

  fid = fopen ("foo.gz", "wz");

you are using zlib functions via a std::ostream object that wraps a
gzFile object, and that doesn't provide a way to get at the underlying
file descriptor or a FILE pointer.

If you want to be tricky, I suppose you could do something like

  #include <cstdio>

  #include <iostream>

  #include <octave/config.h>
  #include <octave/defun-dld.h>
  #include <octave/oct-stream.h>
  #include <octave/c-file-ptr-stream.h>

  DEFUN_DLD (myfun, args, , "")
  {
    octave_stream oct_strm = octave_stream_list::lookup (args(0), "myfun");

    std::ostream *os = oct_strm.output_stream ();

    if (os)
      {
        c_file_ptr_buf *rdbuf = dynamic_cast<c_file_ptr_buf *> (os->rdbuf ());

        if (rdbuf)
          {
            FILE *fp = rdbuf->stdiofile ();

            if (fp)
              fputs ("foobar\n", fp);
            else
              error ("no fp");
          }
        else
          {
            error ("no rdbuf; writing to os");

            *os << "foobar!" << std::endl;
          }
       }
    else
      error ("no os");

    return octave_value ();
  }
      
Hmm.  Maybe we should provide this functionality directly in the
octave_stream class, say a function with an interface like

  FILE * octave_stream::stdiofile (void) const;

What should it do if the stream does not contain a FILE object?  Throw
an error?  Return 0?

Note that currently Octave's stdin, stdout, and stderr streams can't
be converted to FILE pointers because they are really just aliases for
std::cin, std::cout, and std::cerr, though if we provide a stdiofile
function, it might make sense to convert them to octave_stdiostream
objects that wrap the C stdin, stdout, and stderr FILE pointers.

jwe


reply via email to

[Prev in Thread] Current Thread [Next in Thread]