It's ugly code, that's what it is.
What it's basically doing is calling a function (FunctionB
) that returns a pointer to another function, and assigning that pointer to the variable FunctionA
. Now, if that was all that was going on, then the code would look very simple:
FunctionA = FunctionB( var1, var2, etc... );
Unfortunately, for some weird reason (that presumably made a lot of sense to whoever originally designed that API), the return type of FunctionB
is not declared to be a function pointer, but rather a DWORD_PTR
(an integer type that matches the size of a pointer on the underlying platform). That means that the return value of FunctionB
cannot be directly assigned to the variable FunctionA
, but has to be cast into an actual function pointer first (which, as has been noted in the comments, is technically undefined behavior according to the C standard, although e.g. POSIX does define semantics for it).
Now, if the type of the FunctionA
variable was something simple, like, say my_func_ptr_t
, then this would still be easy to write:
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );
But alas, in your code FunctionA
is declared as:
BOOL (WINAPI * FunctionA) (arg1, arg2, etc...) = NULL;
which means that its type is something like BOOL (WINAPI *) (arg1, arg2, etc...)
, and so the cast would look like this:
FunctionA = (BOOL (WINAPI *) (arg1, arg2, etc...)) FunctionB( var1, var2, etc... );
It seems that whoever wrote that code decided that such a cast was too complicated, and instead came up with a trick: instead of casting the return value of FunctionB
into a function pointer, wouldn't it be so much easier to cast FunctionA
into a DWORD_PTR
, like this:
(DWORD_PTR) FunctionA = FunctionB( var1, var2, etc... ); /* this doesn't work :( */
But of course, that won't compile; a cast just converts the value of a variable into another type, and you can't assign something to the converted value. (In technical terms, a cast is not an lvalue.) But wait, you can assign to a dereferenced pointer! So if we...
- take a pointer to
FunctionA
(which will thus be a pointer to a function pointer),
- cast it into a pointer to a
DWORD_PTR
, and
- dereference that pointer,
then we get a valid DWORD_PTR
lvalue that we can assign to, and which just happens to share the same memory address as the variable FunctionA
. Never mind that all this invokes undefined behavior six ways to Sunday according to the C standard — we know our compiler will handle it the way we expect, right?
So, this is precisely what the code does:
&FunctionA
returns a pointer to the variable FunctionA
,
(DWORD_PTR *)
casts this pointer so that it now claims to point to a variable of type DWORD_PTR
, and
- the
*
on the left dereferences this pointer, so that the return value of FunctionB
gets assigned to whatever memory location it points to (which, conveniently, just happens to be the location of FunctionA
).
But of course, all this relies on the (non-standard) assumption that, on the particular compiler and platform this code is meant for, writing a DWORD_PTR
into memory and then using that same memory location as a function pointer actually works and calls the expected function, as opposed to e.g triggering an access violation, jumping into the wrong address, or making demons fly out of your nose.
OK, so it's ugly code. How would I do it better, then?
Well, ideally, I'd change FunctionB
so that it would actually return a function pointer of the appropriate type, so that none of these casting shenanigans would be needed in the first place.
If that really wasn't possible for some reason (and I'd try pretty hard to make it possible, even redesigning the API if necessary), the next best solution would be explicitly casting the return value of FunctionB
. Sure, it's undefined behavior, but at least it's explicit about what it tries to do.
Either way, I would definitely typedef
the actual function pointer type into something more readable. That way, the code (with an explicit cast) might end up looking something like this:
typedef BOOL (WINAPI * my_func_ptr_t) (arg1, arg2, etc...);
my_func_ptr_t FunctionA = NULL;
/* ... */
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );