cglib

Is it expected behaviour that to use the "gstdio" functions in GLib, I need to directly include both glib/gstdio.h and fcntl.h?


I'm writing a C program using GLib targetting Linux, and only Linux (maybe also other Unixes, but it'd be on a best-effort basis if at all). So far, every GLib function I've used has been available by just including glib.h. Of course, for instance GObject features came from glib-object.h and Gio features came from gio/gio.h, but they're treated as separate libraries even if they stem from the same monorepo, so it makes sense to me.

Today I needed to just create a file without writing anything to it, and g_creat () seemed to do just that with a straightforward interface. Given that it's under the GLib documentation namespace and doesn't say anything about including any specific headers, I assumed I'd just be able to use this function like any other GLib function. But that wasn't the case, I got an error that the function didn't exist (or more like that I "implicitly declared" it, but same thing in this context). So, I dove into the source code and found that it was declared in a header called gstdio.h, so I tried including this header directly as glib/gstdio.h. To my surprise, this did work—but the code still didn't compile because creat was still not defined. So, I looked up where creat is defined and found that it comes from fcntl.h. I included fcntl, and now the code compiled as expected.

This leaves me with two (or three) questions:


Solution

  • Why did I need to include glib/gstdio.h directly when GLib typically exposes all functions via glib.h and doesn't allow including other headers directly?

    This is documented:

    The recommended way of using GLib has always been to only include the toplevel headers glib.h, glib-object.h, gio.h. [...]

    Still, there are some exceptions; these headers have to be included separately:

    [...]

    • glib/gprintf.h and glib/gstdio.h (we don’t want to pull in all of stdio)

    (emphasis added.)

    Included in that excerpt is all the rationale I found for that design decision.

    Why did I need to include fcntl.h directly too? Is this intentional or a bug?

    This, too, is documented and apparently intentional:

    On some Unix systems, these APIs may be defined as identical to their POSIX counterparts. For this reason, you must check for and include the necessary header files (such as fcntl.h) before using functions like g_creat(). You must also define the relevant feature test macros.

    That seems more an acknowledgement than a satisfying rationale. I would have expected additional headers not to be needed, since this function is, after all, part of an abstraction layer. But I guess the prevailing philosophy is to minimize the system and standard library headers pulled in by the GLib headers.