void* to pointer
Normally when calling a dynamically loaded function I usually do a standard straight cast:
typedef int (*GenericFn)(); // matches x86 FARPROC, minus explicit calling convention
typedef bool (*DesiredFn)(int,int);
GenericFn address = GetProcAddress(module, "MyFunction");
DesiredFn target = re开发者_高级运维interpret_cast<DesiredFn>(address);
Today I did something a little different (and braindead).
DesiredFn target = nullptr;
void* temp = static_cast<void*>(&target); // pointer to function pointer
GenericFn* address = static_cast<GenericFn*>(temp);
*address = GetProcAddress(module, "MyFunction"); // supposedly valid?
// temp is declared void* because a void** cannot be cast to GenericFn* without
// first doing a void** -> void* conversion
assert(target == MyFunction); // true on VC10, presumably GCC
My questions:
- Is the behavior of a
void*
(note: not avoid**
) to an object pointer type well-defined? - Why does the compiler allow
static_cast<void*>
on avoid**
? - Why am I stupid enough to try this?
- Do you see anything else that's wrong with this example?
I've since decided to use method #1 again because of code clarity (and because I know it's supposed to work). I'm still interested in why method #2 worked though :).
In case you're wondering (about my explanation)
Today I was removing <windows.h>
dependencies in several public interfaces, and rather than redeclare FARPROC
like I should have, I experimentally changed my FARPROC
return-type function to instead accept a void*
output parameter (I know, it should probably have been a void**
).
// implemented in some library cpp file
void detail::FunctionResolve(std::string export, void* output)
{
FARPROC* address = static_cast<FARPROC*>(output);
*address = GetProcAddress(...);
}
// header-defined interface class
template<typename F>
class RuntimeFunction {
F* target;
void SetFunction(std::string export) {
// old: this->target = reinterpret_cast<F*>(detail::FunctionResolve(...));
// new:
detail::FunctionResolve(export, static_cast<void*>(&this->target));
}
};
typedef int (*GenericFn)(); // matches x86 FARPROC, minus explicit calling convention
typedef bool (*DesiredFn)(int,int);
DesiredFn target = nullptr;
void* temp = static_cast<void*>(&target); // pointer to function pointer
There's nothing wrong here, but the cast is unnecessary. A pointer to any object (a pointer to a function is an object) can be converted to a pointer to void
without a cast. e.g.
void* temp = ⌖
GenericFn* address = static_cast<GenericFn*>(temp);
You can convert from a pointer to void
to a pointer to any object type but the results are only defined if you cast a value the was converted to a void*
back to the original type that it was converted from. Technically, only a static_cast<DesiredFn*>(temp)
would have a well defined result.
*address = GetProcAddress(module, "MyFunction"); // supposedly valid?
This isn't technically correct as you have lied about the type of the value that you assigned to address
so address
isn't pointing to an object that matches its type information.
Having said all that, in many implementations function pointers are all represented in the same way and any cast and conversions don't have any effect on the value that is actually stored. So long as you call the function throught a pointer that actually matches the type of the pointer you won't have any problems.
After all, you have to rely on your implementation's behaviour of reinterpret_cast
and GetProcAddress
for the original method to work at all, but - as you say - I would recommend sticking with the reinterpret_cast
approach in this case as it is clearer what is going on.
It doesn't matter because void* and void** are the same size. You're just changing the type. Why not just cast directly to the type you want?
DesiredFn target =
reinterpret_cast<DesiredFn>(GetProcAddress(module, "MyFunction"));
精彩评论