How do I pass a file pointer to my octfile?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

How do I pass a file pointer to my octfile?

baba
Hi all,

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?

Also I have read that you can do type checking using calls like args(0).is_string() and such, but I have not found a place where all of the available functions are described. (the closest I have seen is ov.h). For instance I havent seen a function like is_file_id or equivalent.

any help or pointers to posts tutorials etc is welcome,

thanks,

Baba
Reply | Threaded
Open this post in threaded view
|

How do I pass a file pointer to my octfile?

John W. Eaton
Administrator
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
_______________________________________________
Help-octave mailing list
[hidden email]
https://www-old.cae.wisc.edu/mailman/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: How do I pass a file pointer to my octfile?

baba
Thanks! I got the file pointer using your second "tricky method" using the dynamic cast even though I do not really understand it I must say. But after returning to the calling script, I cannot continue writing to that file.

So in my octave script I can call myOctFunction (FID, ...) and myOctFunction performs some writing to the file as expected. BUT when myOctFunction function returns, it turns out that I can no longer write to the file using fid. In other words in myOctaveScript.m I have something like this:

FID = fopen(myfile, 'w');
myOctFunction( FID, ...); %this works as expected and writes data to the file

fprintf(FID, "some thing"); %does NOT write anything to the file
ftell(fid) %returns -1 !!


I have tried closing, reopening the file and position the pointer to the end:
fclose(FID);
FID = fopen(myfile, 'w');
fseek(FID, SEEK_END);
ftell(fid) %returns 0! so it starts writing at the NEGINNING of the file not the end.


Is there any way of still continue writing to the file from myOctaveScript once myOctFunction(FID, ..) returns?

Thanks!

Baba
Reply | Threaded
Open this post in threaded view
|

Re: How do I pass a file pointer to my octfile?

John W. Eaton
Administrator
On 26-Sep-2010, baba wrote:

| Thanks! I got the file pointer using your second "tricky method" using the
| dynamic cast even though I do not really understand it I must say. But after
| returning to the calling script, I cannot continue writing to that file.
|
| So in my octave script I can call myOctFunction (FID, ...) and myOctFunction
| performs some writing to the file as expected. BUT when myOctFunction
| function returns, it turns out that I can no longer write to the file using
| fid. In other words in myOctaveScript.m I have something like this:
|
| FID = fopen(myfile, 'w');
| myOctFunction( FID, ...); %this works as expected and writes data to the
| file
|
| fprintf(FID, "some thing"); %does NOT write anything to the file
| ftell(fid) %returns -1 !!

It works for me.  If you want help debugging the problem you'll need
to provide a complete example that demonstrates the failure.

| I have tried closing, reopening the file and position the pointer to the
| end:
| fclose(FID);
| FID = fopen(myfile, 'w');

This truncates the file.  You need to use something like

  FID = fopen (myfile, 'a');

| Is there any way of still continue writing to the file from myOctaveScript
| once myOctFunction(FID, ..) returns?

As I said, it works for me.  So show us exactly what you are doing and
maybe someone can help you debug the problem.

jwe
_______________________________________________
Help-octave mailing list
[hidden email]
https://www-old.cae.wisc.edu/mailman/listinfo/help-octave
Reply | Threaded
Open this post in threaded view
|

Re: How do I pass a file pointer to my octfile?

baba
It was my mistake sorry. The fp was closed by one of the functions I called inside myOctFile.
So it now works as expected. Thanks!
Baba