在C中强制转换GetProcAddress返回的指针

Casting GetProcAddress returned pointer in C++

GetProcAddress返回一个函数指针。
假设我们获得了Beep函数的地址(可以在WinBase.h中找到它的声明(包括Windows.h时))

1
2
3
4
BOOL WINAPI Beep(
  _In_  DWORD dwFreq,
  _In_  DWORD dwDuration
);

然后经典代码可能类似于

1
2
3
4
5
6
7
typedef BOOL(__stdcall *pbeep)(DWORD , DWORD );
pbeep beep = NULL;
FARPROC fptr = GetProcAddress(Hnd,"Beep");
beep = reinterpret_cast<pbeep>(fptr);
if( beep != NULL ) {
   beep( 440, 1200 ); //this generates a beep for 1.2 secs...
      }

一切看起来都不错,并且可以正常工作。
我的问题:

考虑到编译器可以"某种方式"从WinBase.h中已经包含的Beep()声明中获取函数指针"信息",有什么办法可以避免typedef声明。
我的目标是以某种方式重用已经包含在.h文件中的信息(返回/参数/等),在该文件中声明了Beep()函数,而不必手动在typedef上重复所有这些信息。当对一个函数执行此操作时就可以了,但是当函数数量增加时,这些typedef确实是一种痛苦,并且是大量错误的根源。
可以做到吗?

编辑;
我即将移至VS 2013,但到目前为止仍在使用VS2008
那么这个想法就是在没有C 11

的情况下进行的


您可以在C 11中创建一个函数来执行此操作(如果可以使Boost.Typeof进行出价,则可以在C 03中执行该功能):

1
2
3
4
5
6
7
8
9
10
template<typename F>
F GetKnownProcAddress(HMODULE hmod, const char *name, F) {
    auto proc = reinterpret_cast<F>(GetProcAddress(hmod, name));
    if (!proc) {/*throw or something*/}
    return proc;
}

int main() {
    auto beep = GetKnownProcAddress(Hnd,"Beep", Beep);
}

如果您愿意使用宏,则可以更进一步:

1
2
3
//where GetKnownProcAddressImpl is the above; also consider the usual STRINGIFY
#define GetKnownProcAddress(hmod, func) GetKnownProcAddressImpl(hmod, #func, func);
auto beep = GetKnownAddressProc(Hnd, Beep);

1
2
3
4
5
6
7
#include <windows.h>

int main()
{
    decltype(Beep)* beep = (decltype(Beep)*)GetProcAddress(GetModuleHandle("Kernel32.dll"),"Beep");
    beep(440, 1200);
}


在c 11中,您可以编写

1
decltype (&Beep) beep_ptr = reinterpret_cast<decltype (&Beep)>GetProcAddress(Hnd,"Beep");

但是我不明白为什么要这么做-如果您已经有一个指向函数的指针,为什么要手动加载呢?


或尝试:-

1
2
3
typedef BOOL (*pbeep)(DWORD, DWORD);
FARPROC fptr = GetProcAddress(Hnd,"Beep");
((pbeep)fptr)( 440, 1200);

1
2
3
4
5
BOOL (__stdcall *beep)(DWORD, DWORD); // beep - pointer to function with parameters (DWORD, DWORD) and result of type bool
(FARPROC)beep = GetProcAddress(Hnd,"Beep");
if( beep != NULL ) {
     beep( 440, 1200 ); //this generates a beep for 1.2 secs...
}