在一般意义上,明确地在函数指针和对象指针之间进行转换是未定义的行为,但POSIX(请参阅:dlsym)和WinAPI(请参阅:GetProcAddress)需要这样做。
考虑到这一点,并且考虑到这样的代码无论如何都是针对特定于平台的API,它对于函数指针和对象指针不兼容的平台的可移植性实际上是无关紧要的。
但 -Wpedantic 无论如何警告它,#pragma GCC diagnostic ignored "-Wpedantic"
无效:
warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
我希望启用 -Wpedantic ,因为它确实提供了很好的警告,但我不希望在关于对象指针的函数指针的无关警告中出现真正的警告和错误管型。
有没有办法实现这个目标?
在Windows上运行GCC 4.8.0(MinGW):
gcc (rubenvb-4.8.0) 4.8.0
代码示例
#include <windows.h>
#include <iostream>
int main (void) {
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl;
}
发出(使用 -Wpedantic ):
warning_demo.cpp: In function 'int main()':
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct
ion and pointer-to-object [enabled by default]
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),
"five")) << std::endl;
^
答案 0 :(得分:4)
我认为你可以在这里使用g ++的system_header
指令:
wrap_GetProcAddress.h:
#ifndef wrap_GetProcAddress_included
#define wrap_GetProcAddress_included
#pragma GCC system_header
template <typename Result>
Result GetProcAddressAs( [normal parameters] )
{
return reinterpret_cast<Result>(GetProcAddressAs( [normal parameters] ));
}
#endif
答案 1 :(得分:3)
这很好用。
template <typename RESULT, typename ...ARGS>
void * make_void_ptr(RESULT (*p)(ARGS...)) {
static_assert(sizeof(void *) == sizeof(void (*)(void)),
"object pointer and function pointer sizes must equal");
void *q = &p;
return *static_cast<void **>(q);
}
答案 2 :(得分:2)
你总能使用memcpy技巧:
int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));
您可以在ideone上看到它:m
is generating warnings, while g
is OK。
至于你可能想要采取的其他行动方案:一个明显的可能性是“修复”定义dlsym
的标题以实际返回一个函数指针(如void (*)()
)。祝你好运。