我应该如何为最终的64位编译器准备我的32位Delphi程序?
可能重复:
如何在迁移到Delphi 2010和Unicode时为64位做准备
因为我相信64位的 Delphi编译器很快就会出现,所以我很好奇,如果有人知道现在使用64位编译器,现在32位的程序是什么样的编译和工作,没有任何改变。
如果有一个普遍的规则,我们应该在我们的旧程序中系统地做出什么样的改变来编译为64位 ?
当64位编译器突然在这里的时候准备好是很好的…
任何build议将不胜感激。
首先,免责声明:虽然我为Embarcadero工作。 我不能为我的雇主说话。 我要写的是基于我自己的意见,假设一个64位的delphi应该如何工作,但是可能会或可能不会有相互竞争的意见和其他预见或不可预见的不兼容性和事件,导致做出替代devise决定。
那就是说:
-
有两种整数types,NativeInt和NativeUInt,其大小将根据平台在32位和64位之间浮动。 他们已经出现了不less新闻。 没有其他的整数types会根据目标的位数改变大小。
-
确保任何依赖将一个指针值转换为一个整数的地方,反之亦然,就是使用NativeInt或NativeUInt作为整数types。 在Delphi的更高版本中TComponent.Tag应该是NativeInt。
-
我build议不要使用NativeInt或NativeUInt非基于指针的值 。 尽量保持你的代码在32位和64位之间的语义相同。 如果你需要32位的范围,使用Integer; 如果你需要64位,使用Int64。 这样你的代码应该在两个位上运行相同的。 只有当你从某个types的指针值(如引用或THandle)转换到另一个值时,才应该使用NativeInt。
-
在可能的情况下,使用
PByte
进行指针算术,优先于NativeInt
或NativeUInt
。 这对于大多数目的来说已经足够了,并且更安全,因为它不能被(容易)误认为正常的整数types,反之亦然。 -
指针类的东西应该遵循与指针类似的规则:对象引用(显然),而且还包括HWND,THandle等。
-
不要依赖string和dynamic数组的内部细节,比如它们的头部数据。
-
我们关于64位API更改的一般策略应尽可能在32位和64位之间保持相同的API,即使这意味着64位API不一定会利用机器。 例如,TList可能只处理MaxInt div SizeOf(指针)元素,以保持Count,索引等等为Integer。 因为整数types不会浮动(即根据比特度更改大小),所以我们不希望对客户代码产生连锁反应:任何通过整数typesvariables或循环索引进行往返的索引都会被截断并可能导致微妙的错误。
-
在API扩展为64位的情况下,他们很可能会使用额外的函数/方法/属性来访问额外的数据,并且这个API也将在32位中得到支持。 例如,Length()标准例程可能会返回Integertypes的值作为string或dynamic数组types的参数; 如果想要处理非常大的dynamic数组,可能会有一个LongLength()例程,它的实现在32位和Length()是一样的。 如果应用于具有2 ^ 32个元素的dynamic数组,则Length()将在64位中引发exception。
-
与此相关的是,可能会改进对语言缩小操作的错误检查,特别是将64位值缩小到32位位置。 如果Length(),则返回Int64,这将影响将Length的返回值分配给Integertypes的位置的可用性。 另一方面,对于像Length()这样的编译魔术函数,可能会有一些优势,例如根据上下文切换返回types。 但是在非魔术API中不可能有类似的优点。
-
dynamic数组可能会支持64位索引。 请注意,即使在64位平台上,Java数组也仅限于32位索引。
-
string可能会被限制为32位索引。 对于想要4GB +string的人来说,我们很难find真正意义上的string,而不仅仅是数据的pipe理blob,dynamic数组也可以用。
-
也许是一个内置的汇编程序,但有限制,就像不能自由混合使用Delphi代码; 还有一些规则需要在x64上遵循exception和堆栈框架布局。
首先, FreePascal已经提供了64位的支持。 不过,这不是delphi。
其次,我期待Delphi 1升级到Delphi 2时存在的问题。最大的问题是大部分与地址空间有关,这里的问题是指针会从4字节扩展到8字节。 在WIN16中,它们使用的是2个字节,需要通过使用指针段和偏移量来克服64KB边界的技巧。 (有可能使用默认段进行多个任务。)
某些数据types也可能比现在更大。 整数types将是8字节,最有可能的。 (以前在Windows 2中只有2个字节)。枚举也可能会变得更大。 但大多数其他数据types可能会保持其当前的大小,所以在这里没有太多的变化。
另一个问题将是内存需求。 由于指针的长度是8个字节,所以使用它们的应用程序也会占用更多的内存。 带有10.000个指针的列表将从40.000字节增加到80.000字节。 您可能要使用比32位系统更多的内存。
速度也会有所改变。 由于处理器现在同时处理8个字节,因此可以更快地处理数据。 但是,由于指针和一些数据types变大,接收或发送到某些设备或内存会慢一点。 一般来说,您的应用程序总体上会稍微快一些,但是有些部分实际上可能会变慢。
最后,Windows API的更改将要求您使用64位API函数。 也许Delphi编译器会做一些聪明的事情来允许代码调用32位API函数,但是这会降低性能,因为处理器现在在本机64位模式和模拟32位模式之间切换。
根据您的代码,您可以尝试使用支持32位和64位编译的FreePascal进行编译。 编译器会在你的代码中警告你可能有错误的地方。
当Delphi 2009宣布Delphi只能创buildUnicode应用程序时,会问到许多类似的问题。 最后发现,大多数现有的代码运行得很好,没有改变。 棘手的部分是假定SizeOf(Char) = 1
和第三方组件可能会这样做的代码。
我希望转向64位delphi是一个类似的经验。 除了使用指针玩弄技巧并假定SizeOf(Pointer) = 4
或SizeOf(Pointer) = SizeOf(Integer)
代码之外,所有东西都只是在盒子中工作。 您现在可以通过调用SizeOf(Pointer)
而不是使用硬编码4
并在需要指针大小的整数时使用NativeInt
或NativeUInt
来解决此类问题。
你应该使用SizeOf(Pointer)
而不是SizeOf(NativeInt)
如果你想让你的代码与Delphi 2007一起工作SizeOf(NativeInt)
2007有一个不幸的错误,导致SizeOf(NativeInt)
返回8而不是4,因为它应该。 delphi2009年修复了这个问题。
绝大多数简单的应用程序应该工作得很好。 据我所知,只有手动使用指针的应用程序处于风险之中。 事实上,如果一个指针现在是64位的,并且将它与整数或基数一起使用(默认情况下仍然是32位),那么您将遇到麻烦。 我也认为,以指针作为参数的API函数的声明使用cardinal
s而不是(无符号)本地整数types是很常见的。
为了使代码在任何平台上运行良好,在同时使用指针和整数时,应该使用NativeUInt
(IIRC,现在没有Deplhi编译器)而不是cardinal
的。
只要Embarcadero不公布关于他们的64位实现的官方信息,不容易说明。 你应该检查指针,Integer和Cardinal的任何types转换,假设它们是本地平台的大小,包括对象的属性和引用(即把一个Integer存储在TObject属性中,这是一个指针,或者使用Tag存储引用而不是数字)。
您还必须确保在最大(最小)大小递增(或递减)值时,没有代码依赖于“绕回”效应。
检查依赖于数据大小的结构中的任何代码,并且不要正确使用SizeOf(),并且在数据大小很重要的时候总是使用SizeOf()。 检查将数据写入/读取文件的代码,如果大小可以更改,尤其是如果数据需要在32位和64位代码之间交换的话。
如果应用程序调用API并直接pipe理Windows消息,请检查Win64更改。 必须检查手写ASM代码的64位兼容性(有更严格的规则来编写64位汇编器)。
除了明显的指针< – >整型任务:(使用intptr / nativeint / ptrint等)
- 任何你有作为一个二进制blob(DLL可能是OCX等)需要升级。 这可能包括旧软件狗的SDK等。
- 所有在二进制级别上执行某些操作的工具(debugging器,分析器,手机主页工具)都可能需要更新。
- 几乎所有的汇编程序和其他非常低级的技巧(例如依赖于VMT布局,debugging格式(追溯)dynamic加载存根,如Jedi Apilib等)都需要更新
- 检查所有自己创build的标题,以确定包装和错误转换中现在指针<>整数的变化。 包装位不容小觑
- 与Office和其他外部应用程序的连接可能会改变
- TComponent.tag现在是一个longint,因此可能会保持longint,这意味着将指针指向component.tag的scheme可能会失败。
- x87 FPU在x64上不推荐使用,一般来说SSE2将用于浮点运算。 所以浮点和exception处理可能稍有不同,扩展可能不是80位(但64位或更less的128位)。 这也涉及到通常的四舍五入(copro控制)的变化,当接口与C代码,期望一个不同的fpu单词。
打包logging问题是我注意到将现有的头文件移植到win64时所注意到的。
我的2美分:
-
在过去,每个ASM作家都被推向了BASE
-
外部asm64将是可以接受的,使用旧的包括xy.obj代码,而任何方式需要一个完整的重写
-
debugging器和CPU64:问题将是这仍然存在?
-
D64浮点扩展:这仍然保持为80位浮点?
生命值
作为一个完整的猜测,任何不依赖于特定单词大小的代码,或者可以根据编译器告诉它的字来调整它的大小,都可以。