我有一个 dlsym() 返回的 void 指针,我想调用 void 指针指向的函数。所以我通过强制转换进行类型转换:
void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = static_cast<fptr>(gptr) ;
我也尝试过reinterpret_cast
,但没有运气,虽然 C cast 运算符似乎工作..
我有一个 dlsym() 返回的 void 指针,我想调用 void 指针指向的函数。所以我通过强制转换进行类型转换:
void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = static_cast<fptr>(gptr) ;
我也尝试过reinterpret_cast
,但没有运气,虽然 C cast 运算符似乎工作..
在 C++98/03 中,不允许将 a直接转换void*
为函数指针(不应使用任何类型转换进行编译)。C++0x 有条件地支持它(实现可以选择定义行为,如果确实定义了行为,那么它必须按照标准所说的去做。A ,如 C++98/03 标准所定义, 是为了指向对象而不是包含函数指针或成员指针。 void*
知道您正在做的事情在很大程度上依赖于实现,这里有一个选项应该long long
在大多数平台上编译和工作(假设 32 位指针,用于 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 - 绝不是定义明确的代码 - 但它应该做你期望它在大多数实现中做的事情。
请注意,C++11 允许这种转换,并且从 gcc 4.9 及更高版本开始,这种转换不会产生警告:https ://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869 。
请参阅 SO 讨论:
好吧,如果您知道参数列表是什么,那么只需 c-cast 它就非常简单。如上所述,它具有未定义的行为,但我一直在我自己的宠物项目事件处理程序中使用它,它似乎在 msvc 上工作得很好。
我可以将相同的 void* 强制转换为 _beginthread_proc_type 以使用 _beginthread 启动线程,这似乎也不会导致任何问题(尽管我真的不知道将参数发送到不需要任何函数的函数的后果,或者不向需要参数的函数发送参数,这似乎至少在我有限的测试中调用了函数/启动线程)
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)) ()
这在 Visual Studio 中编译而不使用 reinterpret cast:
void *ptr;
int (*func)(void) = (int(*)(void))ptr;
int num = func();
我发现了这个(有点难看)的解决方案。具有最高警告级别的 gcc 不会抱怨。此示例调用 dlsym()(返回 void*)并在函数指针中返回结果。
typedef void (*FUNPTR)();
FUNPTR fun_dlsym(void* handle, const char* name) {
union {
void* ptr;
FUNPTR fptr;
} u;
u.ptr = dlsym(handle, name);
return u.fptr;
}
人们可能会使用以下技术:
int (*fn)(int);
*(void **)(&fn) = dlsym(lib1, "function");
int result = (*fn)(3);
或者
fn = (int (*)(int))dlsym(lib1, "function");
编译:
g++ -Wall -pedantic -std=c++11
您可以强制dlsym
转换为返回所需指针的函数,然后像这样调用它:
typedef void (*fptr)();
fptr my_fptr = reinterpret_cast<fptr (*)(void*, const char*)>(dlsym)(RTLD_DEFAULT, name);
PS。将函数指针转换为不同的函数指针然后调用它是未定义的行为(请参阅https://en.cppreference.com/w/cpp/language/reinterpret_cast中的第 7 点),因此最好将结果dlsym
转换为uintptr_t
和然后到所需的类型:
fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(dlsym(RTLD_DEFAULT, name)));
这可能会对您有所帮助。它打印“你好”。
#include <iostream>
void hello()
{
std::cout << "Hello" << std::endl;
}
int main() {
typedef void (*fptr)();
fptr gptr = (fptr) (void *) &hello;
gptr();
}
或者你可以这样做:
fptr gptr = reinterpret_cast<fptr>( (void *) &hello);
其中 &hello 被 dlsym 命令替换。