I'm trying to decipher this declaration from sqlite3.c
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
It seems like it is declaring a function because subsequently there is this
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
return pVfs->xDlSym(pVfs, pHdle, zSym);
}
and then what appear to be calls to the function
xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
and
xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry);
But I cannot make sense of the declaration. I've highlighted what I cannot understand
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
^ ^^^^^^^
I'm wondering why the declaration is not like so
SQLITE_PRIVATE void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);
I expect that there may well be a similar question already asked but searching for terms like (
, )
and void
doesn't really get anywhere. So, if this is a dupe, I'd be very happy for it to be closed as such.
This is declaring a function that returns a function pointer. The return type is void (*)(void)
(SQLITE_PRIVATE
expands to static
and is not part of the return type, per comments), but the function name (and parameters) have to appear inside the (*)
part.
Functions and arrays are the two C type categories that require to do gymnastics to parse. You can think of array types and function types as "decorating" the identifier that they describe. If you write int foo
, you're saying that the symbol "foo" has an integer type. If you write int foo(double)
, you're saying that the symbol foo(double)
has an integer type. foo
and (double)
have to stick together, so any further decoration has to wrap the entire thing as if it was a single name.
The point is best illustrated by mixing array types and function types, even though the end type might not be legal in C. (That says a lot about how ridiculous the syntax is.) For instance:
int foo[5](double)
would be an array (foo[5]
) of functions (int ... (double)
). On the other hand:
int foo(double)[5]
is a function (foo(double)
) and returns an array (int ... [5]
).
The external resource cdecl.org can help you make sense of this kind of declaration. However, you need to replace the structure names with standard types (or write structure types as struct sqlite_vfs
instead of just sqlite_vfs
) for it to understand your declaration.