2

I have to connect two APIs, which use different structures to describe files. One provides me with a std::FILE* and the second one expects a GFile* or GInputStream* belonging to the GIO. Is there a straightforward way to create either object from the raw file pointer which I receive?

void my_function(std::FILE * file) {

GFile * gfile = some_creator_method(file);
//or alternatively
GInputStream * ginput = some_stream_creator_method(file);

//...
//pass the GFile to the other library interface
//either using:
interface_function(gfile);
//or using
interface_stream_function(ginput);
}

//The interface function signatures I want to pass the parameter to:

void interface_function(GFile * f);

void interface_stream_function(GInputStream * is);

geo
  • 435
  • 3
  • 13

1 Answers1

2

If you want to re-use the underlying file handle, you will need to go platform-specific.

For example like this:

void my_method(FILE* file) {
#ifdef _WIN32
    GInputStream* ginput = g_win32_input_stream_new(_get_osfhandle(file), false);
#else
    GInputStream* ginput = g_unix_input_stream_new(fileno(file), false);
#endif

    . . .
    . . .

    g_input_stream_close(ginput, nullptr, nullptr);
}

Keep in mind though that file should be kept open for as long as ginput is in use.

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • 1
    If I were being really fussy, I'd have to say that this doesn't fully answer the question, because it doesn't provide a `GFile *`. But it's not clear whether the OP actually wants the `GFile *`, or just a way to get a `GInputStream *`. – Kevin Boone Sep 15 '20 at 13:19
  • 1
    @KevinBoone `GFile` is not an equivalent of `FILE`; `GFile` does not represent an open file, merely file metadata (name, location). On the other hand, `FILE` represents *only* an open file, without any metadata (well, technically on Linux it's sometimes possible to retrieve the file name from a file descriptor, but I wouldn't recommend it). – rustyx Sep 15 '20 at 13:32
  • Thank you for the answer, but @KevinBoone is right and it does not quite solve my problem. The interface I want to call really expects a GFile * or GInputStream *. I will edit my question to make that clearer. – geo Sep 15 '20 at 13:35
  • 1
    @geo -- Problem is that a `GFile *` is not really analogous to a `FILE *` -- `GFile` is more like a pathname than a stream. If you have an API that takes a `GInputStream *` then the method suggested by @rustyx should work, no? – Kevin Boone Sep 15 '20 at 13:38
  • So I can pass a GUnixInputStream* instead of a GInputStream*? (btw: the library interface itself is exposed in C). – geo Sep 15 '20 at 13:41
  • 1
    @geo `GWin32InputStream` and `GUnixInputStream` both inherit from `GInputStream`, you can supply them anywhere `GInputStream*` is expected. – rustyx Sep 15 '20 at 13:42
  • Is there any way to get a GFile from a file? My interface needs me to set a GFile *and* a GInputStream after all. This is truly driving me insane.... – geo Sep 15 '20 at 13:57
  • 1
    You can create a `GFile` from a file path. If you don't want to pass the file path to your function, you need to somehow get the file path from `FILE*`, which is non-trivial. You can get some inspiration [here](https://stackoverflow.com/questions/58081928/c-print-file-path-from-file) and [here](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew) – rustyx Sep 15 '20 at 14:19