11

在一般意义上,函数指针和对象指针之间的明确转换是未定义的行为,但 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 (MinGW) 上运行 GCC 4.8.0:

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;

       ^
4

3 回答 3

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
于 2013-04-15T23:49:15.700 回答
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);
}
于 2013-04-16T00:07:07.970 回答
2

总有你可以使用的 memcpy 技巧:

int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));

您可以在 ideone: mis generate warnings, while gis OK上看到它。

至于您可能想要采取的其他措施:一种明显的可能性是“修复”定义dlsym为实际返回函数指针(如void (*)())的标头。祝你好运。

于 2013-04-15T23:27:08.330 回答