【问题标题】:stdcall over-ride by visual studio?视觉工作室的stdcall覆盖?
【发布时间】:2010-09-17 16:07:51
【问题描述】:

在 xp 32bit 中,此行编译没有问题,但在 vista 64bit 中,此行:

m_FuncAddr = ::GetProcAddress (somthing);

出现以下错误

错误 C2440:“=”:无法从 'FARPROC' 到 'int (__cdecl *)(void)'

GetProcAddress 定义为

WINBASEAPI FARPROC WINAPI GetProcAddress (somthing)

和 m_FuncAddr 一样

int (WINAPI *m_FuncAddr)();

据我了解,两者都是 stdcall 的。

为了避免我不得不提出的错误

m_FuncAddr = (int (__cdecl *)(void))::GetProcAddress(somthing);

我的问题:

如果 m_FuncAddr 和 GetProcAddress 都有 stdcall 调用约定,为什么我必须用 cdecl 来“调用”它?

VS项目设置'默认调用约定(设置为cdecl)是否有可能覆盖上面的assignemet语句?

提前致谢!

[编辑]

澄清问题:

在等式的一侧(比如第 1 侧)我有

int __stdcall * m_FuncAddr

在另一边(第 2 面)

INT_PTR far __stdcall GetProcAddress

那么,如果两者都是 stdcalls,我必须如何使用 cdecl 投射第 2 面? 还是我没有得到什么?

【问题讨论】:

  • 我的回答在您编辑后仍然有效,int 和 INT_PTR 在 64 位版本中非常不同!
  • 如果您只检查“响应”选项卡,请在下面查看我的编辑。

标签: c++ c windows visual-studio 64-bit


【解决方案1】:

返回类型应为 INT_PTR(64 位构建中的 64 位值)。你不应该绕过这个错误——编译器试图告诉你有问题。

来自 WinDef.h:

#ifdef _WIN64
typedef INT_PTR (FAR WINAPI *FARPROC)();

所以 m_FuncAddr 的声明应该是:

INT_PTR (WINAPI *m_FuncAddr)();

【讨论】:

  • 亚当你的答案是正确的,但请稍微编辑一下,我发现的一件有用的事情是这个错误与我最初认为的调用约定无关。我所做的只是将 m_FuncAddr 返回类型更改为 INT_PTR 并自行解决问题。所以请让你的答案更完整。
【解决方案2】:

巧合的是,它在 32 位下可以正确编译;正确的语法是:

typedef int (WINAPI *FFuncType)();
FFuncType m_FuncAddr;
m_FuncAddr = (FFuncType)::GetProcAddress (somthing);

您需要将 ::GetProcAddress 的结果显式转换为正确的函数签名。在 32 位中,FARPROC 恰好可以使用您拥有的签名,但可能不适用于 64 位。

编辑:是的,事实上,查看 windef.h,返回类型是 64 位的 INT_PTR,所以这就是你得到编译器错误的原因。但是,对于与 FARPROC 的占位符不匹配的任何函数,您仍然需要转换为上述函数签名,因此您应该按照上述方式进行操作。

【讨论】:

  • 但是我认为 FFuncType 是 stdcall 并且我将它转换为 cdecl,或者我没有得到什么?
  • 请记住,即使在 64 位版本中,int 也是 32 位的。
  • 调用约定可能是特定于 DLL 的,因此唯一“安全”的方法是转换为头文件定义的 typedef。可能所有 DLL 都使用相同的约定,但事实上我不知道。
  • 调用约定匹配,两边都是WINAPI。问题是返回类型不匹配(见我的回答)。
  • int vs INT_PTR ?通常只会发出警告......?
猜你喜欢
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
相关资源
最近更新 更多