Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function pointers casting in C++

I have a void pointer returned by dlsym(), I want to call the function pointed by the void pointer. So I do a type conversion by casting:

void *gptr = dlsym(some symbol..) ; typedef void (*fptr)(); fptr my_fptr = static_cast<fptr>(gptr) ; 

I have also tried reinterpret_cast but no luck, although the C cast operator seems to work..

like image 215
sud03r Avatar asked Jul 08 '09 06:07

sud03r


People also ask

Can you cast function pointers?

Yes, it can. This is purpose of casting function pointers, just like usual pointers. We can cast a function pointer to another function pointer type but cannot call a function using casted pointer if the function pointer is not compatible with the function to be called.

What does casting a pointer do in C?

In the C language, casting is a construct to view a data object temporarily as another data type. When you cast pointers, especially for non-data object pointers, consider the following characteristics and constraints: You can cast a pointer to another pointer of the same IBM® i pointer type.

What does casting a pointer mean?

A pointer is an arrow that points to an address in memory, with a label indicating the type of the value. The address indicates where to look and the type indicates what to take. Casting the pointer changes the label on the arrow but not where the arrow points.

What are the function of pointers?

Function pointers in C can be used to create function calls to which they point. This allows programmers to pass them to functions as arguments. Such functions passed as an argument to other functions are also called callback functions.


2 Answers

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.

like image 153
Faisal Vali Avatar answered Oct 03 '22 03:10

Faisal Vali


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?
like image 20
Amir Kirsh Avatar answered Oct 03 '22 05:10

Amir Kirsh