讨鬼传极pc配置要求:使代码与 Win64 兼容

来源:百度文库 编辑:九乡新闻网 时间:2024/05/03 23:17:28
2009-07-23 13:54
msdn 转
将 Win32 代码转换为 x64,所需的最重要的工作可能是确保类型定义正确。还记得先前讨论的 Win64 类型系统吗?通过使用 Windows typedef 类型而非 C++ 编译器的本机类型(int、long 等),Windows 头使得编写干净的 Win32 x64 代码很轻松。您应该在自己的代码中继续保持这一点。例如,如果 Windows 将一个 HWND 传递给您,请不要仅仅为了方便就将其存储在 FARPROC 中。
升级完许多代码之后,我看到的最常见而简单的错误可能就是:假定指针值可以存储或传递到 32 位类型(如 int 和 long)甚至 DWORD 中。Win32 和 Win64 中的指针长度视需要而不同,而整数类型长度保持不变。但是,让编译器不允许指针存储在整数类型中也是不现实的。这是一个根深蒂固的 C++ 习惯。
解救方法是 Windows 头中定义的 _PTR 类型。DWORD_PTR、INT_PTR 和 LONG_PTR 之类的类型可让您声明整数类型的变量,并且这些变量始终足够长以便在目标平台上存储指针。例如,定义为 DWORD_PTR 类型的变量在针对 Win32 编译时是 32 位整数,在针对 Win64 编译时是 64 位整数。经过实践,我已经习惯了声明类型以询问"这里是否需要 DWORD 或者实际是指 DWORD_PTR 吗?"。
正如您期望的,可能有机会明确指定整数类型需要多少字节。定义 DWORD_PTR 及其友元的同一头文件 (Basetsd.h) 还可以定义特定长度的整数,如 INT32、INT64、INT16、UINT32 和 DWORD64。
与类型大小差异相关的另一个问题是 printf 和 sprintf 格式化。我对于在过去使用 %X 或 %08X 格式化指针值感到懊悔万分,并且在 x64 系统上运行该代码时还遇到了阻碍。正确的方法是使用 %p,%p 可以在目标平台上自动考虑指针大小。此外,对于与大小相关的类型,printf 和 sprintf 还具有 I 前缀。例如,您可能使用 %Iu 来打印 UINT_PTR 变量。同样,如果您知道该变量始终是 64 位标记值,则可以使用 %I64d。
在清除了无法用于 Win64 的类型定义所导致的错误之后,可能还有只能在 x86 模式下运行的代码。或者,您可能需要编写函数的两个版本,一个用于 Win32,另一个用于 x64。这就是一组预处理器宏的用武之地:
_M_IX86_M_AMD64_WIN64正确使用预处理器宏对于编写正确的跨平台代码而言至关重要。_M_IX86 和 _M_AMD64 仅在针对特定处理器编译时进行定义。_WIN64 在针对任何 64 位版本的 Windows(包括 Itanium 版)编译时定义。
在使用预处理器宏时,请仔细考虑您的需要。例如,只需要代码真正特定于 x64 处理器,没有别的需要了吗?然后,使用与以下类似的代码:
#ifdef _M_AMD64另一方面,如果同一代码既可以在 x64 又可以在 Itanium 上工作,则使用如下所示的代码可能更好:
#ifdef _WIN64我发现一个有用的习惯是:只要使用其中一个宏,就始终显式创建 #else 情况,以便提前知道是否忘记了某些情况。请考虑以下编写错误的代码:
#ifdef _M_AMD64// My x64 code here#else// My x86 code here#endif如果现在针对第三个 CPU 体系结构编译该代码,会发生什么情况?系统将无意识地编译我的 x86 代码。上面代码的一个更好的表达方式如下:
#ifdef _M_AMD64// My x64 code here#elif defined (_M_IX86)// My x86 code here#else#error !!! Need to write code for this architecture#endif在我的 Win32 代码中无法轻松移植到 x64 的一部分代码是内联汇编,Visual C++ 不支持它的 x64 目标。不要害怕,汇编有办法。它提供了一个 64 位 MASM (ML64.exe),这在 MSDN 中有所说明。ML64.exe 和其他 x64 工具(包括 CL.EXE 和 LINK.EXE)可以从命令行调用。您可以只运行 VCVARS64.BAT 文件,该文件可以将它们添加到您的路径中。