我有一个dlsym()返回的void指针,我想调用void指针指向的函数。 所以我通过强制转换进行类型转换:
void *gptr = dlsym(some symbol..) ;
typedef void (*fptr)();
fptr my_fptr = static_cast<fptr>(gptr) ;
我也尝试过
reinterpret_cast
但没有运气,尽管Ccast运算符似乎有效..
void*
直接转换为函数指针(不应使用任何强制转换进行编译)。它在 C++0x 中有条件地支持(实现可以选择定义行为,如果确实定义了行为,那么它必须执行标准规定的操作。A
void*
,由 C++98 定义) /03 标准,旨在指向对象,而不包含函数指针或成员指针。
知道您正在做的事情很大程度上依赖于实现,这里有一个选项应该在大多数平台上编译和工作(假设 32 位指针,对于 64 位使用
long long
),即使根据标准它显然是未定义的行为:
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 及更高版本开始,此转换不会生成警告:
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 中进行编译,无需使用重新解释转换:
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;
}
您可以将
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)));
可以使用以下技术:int (*fn)(int);
*(void **)(&fn) = dlsym(lib1, "function");
int result = (*fn)(3);
或者
fn = (int (*)(int))dlsym(lib1, "function");
编译:
g++ -Wall -pedantic -std=c++11
typeof 对我有用
//fn_ptr = void_ptr; // error in C++, but works in C
fn_ptr = (typeof(fn_ptr))(void_ptr);
令我惊讶的是 C++ 不会自动执行此操作...
#include <stdio.h>
//#include <cstdint> // uintptr_t
int fn(int x) {
return x + 1;
}
int main() {
void *void_ptr = (void*)&fn;
typedef int (*fn_ptr_t)(int);
#ifndef __cplusplus
// C
fn_ptr_t fn_ptr = NULL;
#else
// C++
fn_ptr_t fn_ptr = nullptr;
#endif
#ifndef __cplusplus
// C
// this just works in C
fn_ptr = void_ptr;
#else
// C++
// error: invalid conversion from ‘void*’ to ‘fn_ptr_t’ {aka ‘int (*)(int)’}
//fn_ptr = void_ptr;
// this works, but its verbose
//fn_ptr = reinterpret_cast<fn_ptr_t>(reinterpret_cast<uintptr_t>(void_ptr));
// cast with typeof. im surprised that C++ does not do this automatically
fn_ptr = (typeof(fn_ptr))(void_ptr);
#endif
// should return 2
return fn_ptr(1);
}
这可能对你有帮助。它打印“你好”。
#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 命令替换。