C++中的函数指针转换

2021-12-31 00:00:00 function-pointers casting c++

我有一个由 dlsym() 返回的 void 指针,我想调用 void 指针指向的函数.所以我通过强制转换来进行类型转换:

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) ;

我也试过 reinterpret_cast 但没有运气,虽然 C 转换运算符似乎工作..

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

推荐答案

void* 转换为函数指针 直接 是不允许的(不应使用任何强制转换)在 C++98/03 中.C++0x 有条件地支持它(一个实现可以选择定义行为,如果它确实定义了它,那么它必须按照标准说它应该做的.A void*,如定义按照 C++98/03 标准,它旨在指向对象而不包含函数指针或成员指针.

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.

知道你在做什么在很大程度上依赖于实现,这里有一个选项应该在大多数平台上编译和工作(假设 32 位指针,使用 long long for 64 位),即使它根据标准显然是未定义的行为:

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; 

或者,慢动作...

// 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;  

它本质上利用了函数指针的地址是一个对象指针的事实(void (**object_ptr)()) - 所以我们可以使用 reinterpret_cast将其转换为任何其他对象指针:例如 void**.然后我们可以沿着地址返回(通过取消引用 void**)到实际的函数指针并将 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 - 绝不是定义明确的代码 - 但它应该可以在大多数实现中执行您期望的操作.

yuk - by no means well-defined code - but it should do what you expect it to do on most implementations.

相关文章