Function pointers casting in C++
well, if you know what the argument list is, it's extremely simple to just c-cast it. As stated above, it has undefined behavior, but I've been using this in my own events handler for a pet project and it seems to work just fine on msvc.
I can cast the same void* to _beginthread_proc_type to start a thread with _beginthread, and that also doesn't seem to cause any issues (though I don't really know what the consequences of sending arguments to a function that doesn't require any, or not sending arguments to functions that do require arguments will do, that does seem to at least call the function/start the thread in my limited testing)
void somefunction(){
std::cout <<"hi"<<std::endl;
}
void* function = (void*)&somefunction;
((void(__cdecl*)(void))(function)) ();
_beginthread((_beginthread_proc_type)function, 0, NULL);
I know the community has developed a hatred for macros, but I use a macro for that function call in my events handler.
#define call_voidstar_function(fc) ((void(__cdecl*)(void))(fc)) ()
Converting a void*
to a function pointer directly is not allowed (should not compile using any of the casts) in C++98/03. It is conditionally supported in C++0x (an implementation may choose to define the behavior and if it does define it, then it must do what the standard says it should do. A void*
, as defined by the C++98/03 standard, was meant to point to objects and not to contain function pointers or member pointers.
Knowing that what you are doing is heavily implementation dependent, here is one option that should compile and work (assuming 32 bit pointers, use long long
for 64 bit) on most platforms, even though it is clearly undefined behavior according to the standard:
void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<long>(gptr)) ;
And here is another option that should compile and work, but carries the same caveats with it as the above:
fptr my_ptr = 0;
reinterpret_cast<void*&>(my_ptr) = gptr;
Or, in Slow motion...
// get the address which is an object pointer
void (**object_ptr)() = &my_ptr;
// convert it to void** which is also an object pointer
void ** ppv = reinterpret_cast<void**>(object_ptr);
// assign the address in the memory cell named by 'gptr'
// to the memory cell that is named by 'my_ptr' which is
// the same memory cell that is pointed to
// by the memory cell that is named by 'ppv'
*ppv = gptr;
It essentially exploits the fact that the address of the function pointer is an object pointer (void (**object_ptr)()
) - so we can use reinterpret_cast
to convert it to any other object pointer: such as void**
. We can then follow the address back (by dereferencing the void**
) to the actual function pointer and store the value of the gptr there.
yuk - by no means well-defined code - but it should do what you expect it to do on most implementations.
Note that C++11 allows such a conversion and from gcc 4.9 and above this conversion does not generate a warning: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869.
See SO discussions:
- Casts between pointer-to-function and pointer-to-object in C and C++
- Why are function pointers and data pointers incompatible in C/C++?
- can void* be used to store function pointers?
- Using reinterpret_cast to cast a function to void*, why isn't it illegal?