C中的函数指针转换

新手上路,请多包涵

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

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

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

原文由 sud03r 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 995
2 个回答

在 C++9803 中,不允许将 void* 直接 转换为函数指针(不应使用任何类型转换进行编译)。 C++0x 有条件地支持它(实现可以选择定义行为,如果它确实定义了它,那么它必须按照标准所说的去做。A void* ,由C++9803 标准,旨在指向对象而不是包含函数指针或成员指针。

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

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

这是另一个应该编译和工作的选项,但带有与上面相同的警告:

 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 的值存储在那里。

yuk - 绝不是定义明确的代码 - 但它应该做你期望它在大多数实现中做的事情。

原文由 Faisal Vali 发布,翻译遵循 CC BY-SA 4.0 许可协议

好吧,如果您知道参数列表是什么,那么只需 c-cast 它就非常简单。如上所述,它具有未定义的行为,但我一直在我自己的宠物项目事件处理程序中使用它,它似乎在 MSVC 上工作得很好。

我可以将相同的 void* 转换为 _beginthread_proc_type 以用 _beginthread() 9d241823641c1d43fb375241c1d43fb375242c015d0d5— 开始一个线程(尽管我似乎也不会引起任何问题真的知道向不需要任何参数的函数发送参数或不向需要参数的函数发送参数会产生什么后果,这似乎至少在我有限的测试中调用了函数/启动线程):

 void somefunction(){
    std::cout <<"hi"<<std::endl;
}

void* function = (void*)&somefunction;
((void(__cdecl*)(void))(function)) ();

_beginthread((_beginthread_proc_type)function, 0, NULL);

我知道社区已经对宏产生了仇恨,但我在我的事件处理程序中使用宏来调用该函数:

 #define call_voidstar_function(fc)     ((void(__cdecl*)(void))(fc)) ()

原文由 Val 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题