[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