How do I correctly define an inline function that dereferences an opaque pointer according to the C99 standard? Let's say I've organized a program in three files:
opaq.h:
typedef struct Opaq Opaq;
Opaq* opaq_init(void* ptr, int size);
void opaq_free(Opaq* o);
inline int opaq_size(Opaq* o);
opaq.c:
#include <stdlib.h>
#include "opaq.h"
struct Opaq {
void* ptr;
int size;
};
Opaq* opaq_init(void* ptr, int size)
{
Opaq* o = malloc(sizeof(*o));
o->ptr = ptr;
o->size = size;
return o;
}
void opaq_free(Opaq* o)
{
free(o);
}
int opaq_size(Opaq* o)
{
return o->size;
}
main.c:
#include <stdlib.h>
#include "opaq.h"
int main(void)
{
Opaq* o;
int size;
o = opaq_init(NULL, 3);
size = opaq_size(o);
opaq_free(o);
return 0;
}
I would like opaq_size to be inlined in main.c. Such inlining is possible to my knowledge as inlining can occur during linkage. However, trying to compile this with GCC gives the following warning:
$ gcc -Winline -o main main.c opaq.c
In file included from main.c:2:0:
opaq.h:5:12: warning: inline function ‘opaq_size’ declared but never defined
inline int opaq_size(Opaq* o);
Using the keyword extern in opaq.h gives the same warning. Compiling with -fgnu89-inline resolves the warning, however disassembling main reveals that inlining did not actually occur. Notice I cannot define the function in the header (as static inline), as the structure definition is out of scope.
No, a compiler cannot inline something it doesn't know about. A classical linker cannot do it either because the object files are already compiled.
The point of an opaque pointer is to make translation units independent of the type behind the pointer (usually to offer an stable ABI to clients), so it is not clear what you are trying to accomplish. If you inline in any way, including things like LTO (Link-Time Optimization), they won't be independent anymore.
In summary, do not use an opaque pointer if you don't need the guarantees it provides.