我应该如何为最终的64位编译器准备我的32位Delphi程序?

Pet*_*tra 59 delphi unicode 32bit-64bit delphi-2010

可能重复:
迁移到Delphi 2010和Unicode时如何准备64位

由于我相信64位 Delphi编译器很快就会出现,我很好奇是否有人知道现在32位的程序将在使用64位编译器时编译和工作而不做任何更改.

如果有一般规则,我们应该在旧程序中系统地进行哪些更改以编译为64位

64位编译器突然出现时,做好准备是很好的 ...

任何建议将不胜感激.

Bar*_*lly 80

首先,免责声明:虽然我为Embarcadero工作.我不能代表我的雇主.我要撰写的内容是基于我自己对假设的64位Delphi应该如何工作的看法,但可能存在或不存在竞争性意见以及导致替代设计决策的其他预见或不可预见的不兼容性和事件.

那说:

  • 有两种整数类型,NativeInt和NativeUInt,其大小将在32位和64位之间浮动,具体取决于平台.他们已经出现了不少版本.没有其他整数类型会根据目标的位数改变大小.

  • 确保依赖于将指针值转换为整数的任何位置(反之亦然)使用NativeInt或NativeUInt作为整数类型.TComponent.Tag在Delphi的更高版本中应该是NativeInt.

  • 我建议不要将NativeInt或NativeUInt用于非基于指针的值.尝试在32位和64位之间保持代码在语义上相同.如果需要32位范围,请使用Integer; 如果您需要64位,请使用Int64.这样你的代码应该在两个位上都运行相同.只有当你使用某种类型的Pointer值(例如引用或THandle)进行转换时,才应使用NativeInt.

  • 使用PByte了指针运算在可能情况下,优先于NativeIntNativeUInt.它足以满足大多数目的,并且更加类型安全,因为它不能(容易)被误认为是普通的整数类型,反之亦然.

  • 类似指针的东西应该遵循与指针类似的规则:对象引用(显然),还有像HWND,THandle等的东西.

  • 不要依赖字符串和动态数组的内部细节,比如它们的标题数据.

  • 我们关于64位API更改的一般策略应该是尽可能在32位和64位之间保持相同的API,即使这意味着64位API不一定利用机器.例如,TL​​ist可能只处理MaxInt div SizeOf(指针)元素,以便将Count,索引等保持为Integer.因为Integer类型不会浮动(即根据位数改变大小),我们不希望对客户代码产生连锁反应:任何通过Integer类型变量或for循环索引往返的索引都会被截断并可能导致细微的错误.

  • 在API扩展为64位的情况下,它们很可能使用额外的函数/方法/属性来访问额外的数据,并且此API也将以32位支持.例如,对于类型为string或dynamic array的参数,Length()标准例程可能会返回Integer类型的值; 如果想要处理非常大的动态数组,可能还有一个LongLength()例程,其32位实现与Length()相同.如果应用于具有超过2 ^ 32个元素的动态数组,则Length()将在64位中引发异常.

  • 与此相关,可能会改进错误检查以缩小语言中的操作范围,特别是将64位值缩小到32位位置.如果长度()返回Int64,这将会影响将Length的返回值赋给Integer类型的位置的可用性.另一方面,特别是对于像Length()这样的编译器魔术函数,可能会有一些优势,例如根据上下文切换返回类型.但是在非魔术API中不能同样采用优势.

  • 动态数组可能支持64位索引.请注意,Java阵列仅限于32位索引,即使在64位平台上也是如此.

  • 字符串可能仅限于32位索引.对于想要4GB +字符串的人来说,我们很难找到真正的字符串,而不仅仅是托管数据块,动态数组也可以用它们.

  • 也许是一个内置的汇编程序,但有限制,就像不能自由地混合使用Delphi代码; 在x64上还需要遵循异常和堆栈框架布局的规则.

  • 哎呀,没有汇编会伤害我很多.我的视觉应用程序中有很多SSE代码.是的我知道,我可能不得不通过x86_64中的push/popping reg来改变它们,但是更新比找到不同的解决方案更新. (17认同)
  • @Marco:+1.没有ASM会伤害很多人. (6认同)
  • @Marco:没有ASM的+1.对我来说这也是一个很大的缺点(一个老式的汇编程序员:-)). (6认同)
  • 对于`inline`子程序,BASM支持瘫痪,现在即将删除BASM.我很欣赏Ribbon支持,但我更喜欢编写快速代码.这个未来很糟糕. (5认同)
  • 我也想念ASM. (4认同)
  • AFAIK汇编程序支持也在Visual C++ 64位中删除.如果需要汇编程序代码,则必须在外部编译然后链接.汇编程序代码的64位必需条件非常严格,以至于手写汇编程序可能存在问题.缺点是我猜Embarcadero不会带回TASM - 需要单独的编译器. (3认同)
  • 我怀疑编写实际需要64位支持的应用程序的人和关心asm的人之间存在一定的相关性.:) (3认同)
  • @Barry Kelly ......所有三个样本集(大数据集,shell集成,老屁)都是那些偶尔写asm的人(而不是那些建立业务逻辑的年轻人):).不知何故,必须在单独的文件中重写和维护asm(通过单独的工具集)的声明"并不困难",这有点像来自构建IDE的人.这个首字母缩略词的I部分很重要,而不仅仅是应用程序的pascal部分. (3认同)
  • @HeartWare - 更大的问题是32位和64位之间的语义差异.我们越多可以最小化这些,越好.16位到32位是不同的,因为许多应用程序在许多计数器中需要超过16位; 但很少有应用程序需要超过32位的通用整数.在RTL和用户代码中还存在32位和64位值之间的转换问题.假设大多数用户代码使用Integer,那么API使用64位Int64会导致截断警告(预期会增加警告)会很痛苦.对于大多数API,限制为32位是可以的. (2认同)
  • 嗯,RTL怎么样?这是否意味着64位RTL的下游不会出现在Pascal中? (2认同)
  • @Marco:+ 1没有asm,我真的很想念它 (2认同)
  • 仅仅为了记录,我正在添加"构建64位COM AddIns"和"64位MAPI应用程序"到我们处于64位支持的等待和抱怨行的原因列表中.是的,64位办公套餐的销售百分比很小,但由于数量庞大,它仍然是真正的客户群. (2认同)

Wim*_*ink 8

首先,FreePascal已经提供64位支持.不过,这不是德尔福.
其次,我预计Delphi 1升级到Delphi 2时存在同样的问题.最大的问题是与地址空间有关,这里的问题是指针将从4个字节扩展到8个字节.在WIN16中,它们使用2个字节,并且需要通过使用段和指针偏移来克服64KB边界的技巧.(可以为多个任务使用默认段.)
某些数据类型也可能会变得比现在更大.整数类型最有可能是8个字节.(以前在Windows 2中仅为2个字节.)枚举可能也会变大.但是大多数其他数据类型可能会保持其当前大小,因此这里没有太多变化.
另一个问题是内存要求.由于指针长度为8个字节,因此使用大量指针的应用程序也会占用更多内存.具有10.000个指针的列表将从40.000字节增加到80.000字节.您可能希望使用比32位系统更多的内存.
速度也会有所改变.由于处理器现在可以同时处理8个字节,因此它可以更快地处理数据.但是,由于指针和一些数据类型变得更大,接收或发送到某些设备或内存将会慢一点.通常,您的应用程序通常会稍微快一些,但某些部分实际上可能会变慢!
最后,Windows API中的更改将要求您使用64位API函数.也许Delphi编译器会做一些聪明的事情来允许代码调用32位API函数,但这会降低性能,因为处理器现在在本机64位模式和模拟32位模式之间切换.

  • @Workshop Alex - 我是Emabarcadero Delphi编译团队的成员; 相信我,当我说整数将保持32位:) (10认同)
  • 在64位Windows上,该模型用于int和long以保持32位.相应地,Delphi将跟随Integer和Longint保持32位.此外,在Delphi中,枚举始终具有能够表示其范围的最小类型. (7认同)

Eug*_*its 5

根据您的代码,您可以尝试使用 FreePascal 进行编译,它支持 32 位和 64 位编译。编译器会警告您代码中可能存在错误的地方。


Jan*_*rts 5

当宣布 Delphi 2009 将仅创建 Unicode 应用程序时,人们提出了许多类似的问题。最后发现大多数现有代码无需更改即可正常运行。棘手的部分是假设的代码SizeOf(Char) = 1以及可能这样做的第三方组件。

我预计迁移到 64 位 Delphi 也会有类似的体验。一切都可以开箱即用,除了那些用指针玩弄花样并假设SizeOf(Pointer) = 4or 的代码SizeOf(Pointer) = SizeOf(Integer)。今天,当您需要指针大小的整数时,您已经可以通过调用SizeOf(Pointer)而不是硬编码4和使用NativeIntor来解决此类问题。NativeUInt

如果您希望您的代码能够与 Delphi 2007 一起工作,则应该使用SizeOf(Pointer)而不是SizeOf(NativeInt)。Delphi 2007 有一个不幸的错误,导致SizeOf(NativeInt)返回 8 而不是应有的 4。该问题已在 Delphi 2009 中修复。


Ign*_*ams 1

作为一个完整的猜测,任何不依赖于特定字长的代码,或者可以根据编译器告诉它的内容调整其字长,都可以。