Requirements
------------

- Any code can simply #include <gwy.h> and get an inlinable function. This is obviously necessary for the function
  to be usable inline.
- Any code linking to the library also gets a linkable version (a symbol). This is necessary for instance for
  gobject-introspection.

Combining the two is hairy.


C linkage/scope options
-----------------------

- static inline

  It allows third party code to get the function as inline (good).

  It prevents providing a neatly linkable version because the compiler cannot ever see both static inline and
  extern for the same symbol (bad).

  It makes it invisible for introspection. Probably may be worked around adding some introspection-only stuff and
  renaming annotations (ugly).

- extern inline

  It provides a linkable version (good).

  Multiple translations unit cannot all see the definition. It must be provided exactly once which we cannot really
  ensure for public functions meant for third party code, only for functions used internally in the library (bad).

  They can probably be made visible for introspection but again having to work around the single definition (ugly).

- inline

  Plain inline with neither extern nor static is even less helpful than the two others. It cannot be called from other
  translation units.

There are some compiler- and linker-specific features which can give us what we want. However, portability is an
issue then. Macros may be the least bad solution.


Macro solution
--------------

Header:

extern gdouble gwy_foo(void);

#ifndef __GI_SCANNER__
#ifndef __GTK_DOC_IGNORE__

#define gwy_foo _gwy_foo_implementation

G_GNUC_UNUSED
static inline gdouble
_gwy_foo_implementation(void)
{
    return 1.25;
}

#endif
#endif


Source:

#undef gwy_foo

gdouble
gwy_foo(void)
{
    return _gwy_foo_implementation();
}


This achieves:
- All code and gi-scanner see the extern symbol gwy_foo() declared since as it comes first.
- Any code is redirected to the the inline implementation, which is actually _gwy_foo_implementation().
- Since _gwy_foo_implementation() is static inline, nothing can link to it and it never polutes any symbol table.
- Any code which really wants to dlopen or link to the function (gi.repository) can do so.


Ugly bits
---------

The largest remaning ugly bit is that some C code may really want to see the extern version of the function. It then
must get rid of the redirection macro. The least contrived reason is being able to identify functions by address across
different compilation units. However, since this is still niche and would require *all* relevant code compiled like
this, we do not provide a dedicated flag to disable the indirection macros. Do a bunch of #undefs and send a bug report
if it makes you sad?

A small ugly bit is the #undef-ing before implementing the extern function. It should be done at the end of a source
file so that there is no following code that sees the externs instead of the inlines. However, this is somewhat
fragile. When there are a bunch of functions like that, make a separate file that just provides the extern functions
(math--inlines.c).

The inline implementation should (and sometimes needs to be) excluded for tools like gtk-doc and gi-scanner to ensure
they pick up only the extern and are not confused by the macro and inline code. However, all the guard macros are
tool-specific; there is no *universal* way to do it.


# vim: set tw=119 :
