C++中的函数指针转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1096341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Function pointers casting in C++
提问by sud03r
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:
我有一个由 dlsym() 返回的 void 指针,我想调用 void 指针指向的函数。所以我通过强制转换进行类型转换:
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..
我也试过reinterpret_cast
但没有运气,虽然 C 转换运算符似乎工作..
回答by Faisal Vali
Converting a void*
to a function pointer directlyis 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.
在 C++98/03 中不允许将 a直接转换void*
为函数指针(不应使用任何强制转换进行编译)。C++0x 有条件地支持它(一个实现可以选择定义行为,如果它定义了它,那么它必须按照标准说它应该做的。A ,如 C++98/03 标准所定义, 旨在指向对象,而不是包含函数指针或成员指针。 void*
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:
知道你正在做的事情在很大程度上依赖于实现,这里有一个选项应该long long
在大多数平台上编译和工作(假设 32 位指针,用于 64 位),即使根据标准它显然是未定义的行为:
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.
它本质上利用了函数指针的地址是对象指针 ( void (**object_ptr)()
)这一事实——因此我们可以使用reinterpret_cast
它来将其转换为任何其他对象指针:例如void**
. 然后我们可以沿着地址返回(通过取消引用void**
)到实际的函数指针并将 gptr 的值存储在那里。
yuk - by no means well-defined code - but it should do what you expect it to do on most implementations.
yuk - 绝不是定义明确的代码 - 但它应该做你期望它在大多数实现中做的事情。
回答by Amir Kirsh
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.
请注意,C++11 允许这样的转换,并且从 gcc 4.9 及更高版本开始,此转换不会生成警告:https: //gcc.gnu.org/bugzilla/show_bug.cgi?id=57869。
See SO discussions:
请参阅 SO 讨论:
回答by BrunoLevy
I found this (a bit ugly) solution. gcc with maximum warning level does not complain. This example calls dlsym() (that returns a void*) and returns the result in a function pointer.
我发现了这个(有点难看)的解决方案。具有最高警告级别的 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;
}
回答by Yuriy
One might use the following technique:
可以使用以下技术:
int (*fn)(int);
*(void **)(&fn) = dlsym(lib1, "function");
int result = (*fn)(3);
Or
或者
fn = (int (*)(int))dlsym(lib1, "function");
Compiled with:
编译:
g++ -Wall -pedantic -std=c++11
回答by Elviss Strazdins
You can cast dlsym
to a function that returns the required pointer and then call it like this:
您可以dlsym
转换为返回所需指针的函数,然后像这样调用它:
typedef void (*fptr)();
fptr my_fptr = reinterpret_cast<fptr (*)(void*, const char*)>(dlsym)(RTLD_DEFAULT, name);
PS. Casting a function pointer to a different function pointer and then calling it is undefined behavior (see point 7 in https://en.cppreference.com/w/cpp/language/reinterpret_cast) so it is better to cast the result of dlsym
to uintptr_t
and then to the required type:
附注。将函数指针转换为不同的函数指针然后调用它是未定义的行为(请参阅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)));
回答by Andrew Best
This compiles in Visual Studio without using reinterpret cast:
这在 Visual Studio 中编译而不使用重新解释强制转换:
void *ptr;
int (*func)(void) = (int(*)(void))ptr;
int num = func();
回答by Ryan Oberoi
This may help you. It prints "Hello".
这可能对你有帮助。它打印“你好”。
#include <iostream>
void hello()
{
std::cout << "Hello" << std::endl;
}
int main() {
typedef void (*fptr)();
fptr gptr = (fptr) (void *) &hello;
gptr();
}
OR you can do:
或者你可以这样做:
fptr gptr = reinterpret_cast<fptr>( (void *) &hello);
where &hello is replaced by the dlsym command.
其中 &hello 被 dlsym 命令替换。