admin 管理员组文章数量: 887007
Delphi的一个基本事实是,全世界存在使用较旧版本Delphi编写的大量应用程序软件。尤其是经典的Delphi 7,然而现在是2021年,是时候升级到Delphi 10.4.1新版本了。每天都会有人问我有关从15到20年的旧版本Delphi迁移到最新版本Delphi的问题。值得庆幸的是,Delphi使数十年来的迁移相对容易,但是,这并不意味着轻松!
本页面旨在解决最常见的陷阱,这些陷阱可能是从2009年之前的任何版本的Delphi(包括Borland版本)过渡到现代的Embarcadero Delphi版本的陷阱。
我希望此页面成为一份生动的文档,随着时间的推移我将对其进行更新以包括我发现的所有陷阱。我还将致力于为迁移过程添加提示和技巧,并提供相关文档的链接。
如果您发现其中未包含的内容,请注册并发表评论,我可能会将其集成到此页面中。
跨平台的期望。
在开始研究版本迁移的常见陷阱之前,我想花一点时间(实际上是一两个好页面)来讨论现代Delphi版本经常被误解的功能。如果您对将代码迁移到移动平台或MAC桌面没有兴趣,请继续跳到标题为“ Windows 64位迁移”的部分,我们将从那里开始。
现代新版本 Delphi能够编译代码以定位Windows 32位和64位,MAC OSX,Android和iOS。这个事实导致人们期望Delphi可以使用您的Windows应用程序,并以某种方式使其跨平台。这不是真的!如果它是真的,那将是某种真正的魔法,但事实并非如此。事实是这样:Delphi的现代版本可以为Windows,Mac OSX,Android和iOS编写应用程序。
如果您的应用程序最初是为Windows编写的,则它将使用Win32 API。如果您的应用程序是VCL应用程序,则它使用Win32 API。在Mac OSX,Android和iOS上不可用的一件事是Win32 API。看看我要去哪里?如果不进行重大代码修改,您的应用程序将无法在其他平台上运行。值得庆幸的是,虽然Delphi不会为您神奇地解决此问题,但仍有一些辅助工具可以帮助您…
跨平台应用程序是针对名为FMX的新框架编写的。(以前称为FireMonkey,FMX = FireMonkey X平台)。
FMX框架不依赖Win32 API及其控件,而是实际上使用OpenGL或DirectX打开渲染上下文,并将控件直接渲染到该API。这样,可视控件就可以跨平台。FMX框架具有Delphi随附的绝大多数VCL控件的镜像控件,例如,VCL和FMX都具有TEdit控件,它们都具有TButton控件,依此类推。
有一个名为“ Mida转换器”的工具(请参见此处),它可以打开您现有的VCL表单(.dfm文件),并对其进行修改以使用FMX版本的控件而不是VCL控件。这样,该表格就可以有效地从VCL移植到FMX,因此可以用于Windows以外的平台。但是,这种方法仍然存在一两个陷阱。Mida转换器仅是复制/替换宏工具,如果您使用的控件不是VCL的一部分(例如第三方控件),则Mida转换器无法迁移这些控件,您必须跟踪该控件的FMX版本(如果存在),或从另一个第三方供应商那里替代FMX。
这样的FMX组件供应商之一是TMS软件:https : //www.tmssoftware/site/tmsfmxpack.asp
跨平台的其他注意事项
从仅Windows应用程序迁移到跨平台解决方案时,除了视觉控件外,还有其他一些注意事项。首先,除Windows之外,Delphi支持的所有平台都以某种方式基于unix / linux变体,因此都基于POSIX。因此,需要考虑一些事情……
- POSIX平台具有不同的文件系统。Android,iOS或MAC设备上没有“ C:”驱动器。如果您已将Windows路径硬编码到应用程序中,则可能需要使用条件定义来修改代码,以了解同一文件在其他平台文件系统上的位置。
- 没有注册表。尽管某些平台提供了Windows注册表的模拟功能,但大多数平台都没有这种功能。相反,配置通常存储在特定目录中。“ / etc”目录最常用于存储配置文件,并且没有预先指定的文件格式。一个应用程序可能使用.ini文件或类似的名称/值对文件,而另一个应用程序可能使用JSON文件,而另一个应用程序可能使用XML文件。如果您的VCL应用程序依赖于注册表中的配置,则必须将其迁移到其他平台的配置目录下的文件中。如果您的VCL应用程序通过更改注册表项来修改OS或其他应用程序的行为,则您将不得不找出如何在其他平台上实现相同功能的方法。
- 没有Kernel32。如果您正在使用Windows API的自定义调用,则必须找到替代平台的等效行为。在许多情况下,FMX类将提供答案,但是如果您的应用程序是VCL,则可能不使用这些类。
- 并非所有TCanvas都相等。如果您的代码或第三方供应商的代码直接调用TCanvas进行渲染,或更糟糕的是,直接调用GDI,则需要迁移此代码以在其他平台上工作。FMX框架与VCL一样具有TCanvas,但是方法并不完全相同,它们还具有不同的参数列表。这是不可避免的,因为VCL TCanvas正在渲染到Windows GDI界面,而FMX TCanvas正在使用OpenGL或DirectX等3D API渲染。即使对于2D渲染也是如此,因为现代图形卡根本不再提供2D渲染,而是希望您将2D图形渲染到3D空间中,然后使用特殊的视角模式查看它们,从而减少Z轴。抱歉,您也必须迁移TCanvas代码。
更多信息:使用FMX TCanvas - 您的数据库驱动程序可能不存在。许多开发人员熟悉如何使用名为TConnection,TTable和TQuery的组件(或类似的等效名称)直接连接到数据库。这些组件集通常依赖于某些二进制驱动程序,不幸的是,除非您使用的是InterBase,可能没有针对您所针对的基于ARM- * nix的移动平台的驱动程序版本。您可能无法将应用程序直接连接到数据库,即使可以,您也可能不想在许多移动方案中使用可能不稳定的Internet连接。解决此问题的最常见方法是使用基于REST的Web服务(以SOAP服务构成第二常见的解决方案)以JSON形式公开数据。Delphi有几个用于JSON / REST / SOAP的组件,甚至可以为您将JSON服务改编为TQuery样式的组件,但是您必须从旧的数据访问组件中迁移出来。
- 更多信息:带有Delphi的JSON / REST。
- 更多信息:为什么不应该将移动应用程序连接到数据库。
- 更多信息: Delphi的BaaS解决方案
- 更多信息:Datasnap教程。
- 更多信息:Datasnap和FireDAC公开了MSSQL
- 移动编译器之间存在一些差异。Delphi通过使用多个编译器来实现其单一源代码,多个目标平台的功能。一种用于Windows 32的编译器,另一种用于Windows 64的编译器,而另一种用于android,iOS和Mac的编译器。好吧,尽管所有这些编译器都是99.9%,但并不是所有的编译器都是100%兼容的。
- ARC。移动编译器使用ARC(自动引用计数)内存模型,因此您的代码需要设置为“ ARC安全”,可以通过不破坏桌面平台代码的方式来实现,但是,您需要了解ARC及其如何工作以确保您的代码安全。不这样做会导致难以跟踪的错误。
ARC上的Marco Cantu:http: //blog.marcocantu/blog/delphi_arc_android.html - 没有 Ansi String字符串。 移动编译器完全不支持ansi字符串。缺少诸如StrAlloc(),StrDispose()之类的函数,并且如果您绝对必须使用ansi字符串,那么您就必须将它们放入数组或缓冲区中并使用指针进行处理-但您可能应该放弃在ansi字符串上,不再有现代OS或现代软件使用它们了!Unicode迁移可能会引起一些恐惧,但是它并不太可怕,而且值得,我们将在本页后面看到。
- 字符串索引从零开始!所有其他 数组样式的访问都从零开始索引,但是由于某种原因,字符串中的旧Pascal索引字符从1开始。如果我确实知道为什么会这样,那么我早就被遗忘了,但是对于移动编译器而言,情况已不再如此。字符串现在从零开始索引。不幸的是,这只是我们必须吞下的东西。很长一段时间以来,我们都摆脱了字符串奇数的问题,但是现在该让这种长期存在的句法虚假标准停止了。
- ARC。移动编译器使用ARC(自动引用计数)内存模型,因此您的代码需要设置为“ ARC安全”,可以通过不破坏桌面平台代码的方式来实现,但是,您需要了解ARC及其如何工作以确保您的代码安全。不这样做会导致难以跟踪的错误。
关于跨平台迁移的最终决定和一些希望。
大多数错误地期望Delphi将其应用程序迁移到其他平台的开发人员,也缺少一个关键的重要细节,因为他们实际上可能根本不想将其应用程序迁移到那些平台!如果您在其中,请和我在一起。移动屏幕很小,并且用笨拙的手指来操作,而不是使用鼠标的优雅精度。与台式机相比,移动设备还缺少资源(RAM,磁盘空间,CPU周期等)。如果您将VCL应用程序直接迁移到FMX并将其部署到移动设备上,则很有可能在如此小的屏幕上无法使用,或者由于缺少设备资源而表现糟糕。
在许多情况下,更明智的策略是考虑为您的移动应用程序启动一个全新的项目。这个“伴侣应用程序”项目仍然可以使用您大部分的非可视代码,毕竟仍然很麻烦,但是您可以将新项目限制为仅在移动设备上有意义的那些功能。而且,Delphi附带了一些类,以帮助将您的移动伴侣应用程序集成到现有桌面应用程序旁边的网络中。例如,使用应用程序绑定 类,您的移动应用程序可以直接调用桌面应用程序内的操作,并双向共享数据。
Windows 64位迁移。
从Windows 32位到Windows 64位的迁移要比迁移到完全不同的平台少得多,但是我在这样做时遇到了一个陷阱。
假设整数和指针具有相同的大小(32位),这在Delphi开发人员社区中已成为相当普遍的做法,并且鉴于Delphi中的类实例实际上只是一种特殊的指针,您可以有效地类型转换为一个整数类,用于存储在整数数组中。除此之外,VCL的可视类的.TAG属性也是32位整数,并且可能已被某些类型转换拼图工具用作对象指针。好吧,如果您已完成此操作,或者正在编译执行此操作的第三方源,则现在遇到了问题。在Windows 64位下,指针当然是64位宽,但是整数类型仍然是32位宽。您需要更改此代码以说明不同的数据类型。添加了一些新的整数数据类型以辅助操作。
现在,在开始编写64位代码之前,请问自己是否确实需要这样做?对64位代码有很多常见的误解,并且升级到它通常没有什么好处。我们所处的情况与计算机从8位时代迁移到16位或从16位时代迁移到32位时代的情况不同。
您会看到,将应用程序升级到64位的最常见原因之一是为应用程序提供了更多可寻址的内存空间。对于8位,您只能寻址256字节的RAM,并且要实现更多功能,需要某些存储体切换操作,这会花费处理时间。使用16位可以使事情有所改善,您可以处理高达64k的RAM,并且仍然需要进行组切换以利用更多的内存。进入32位模式,您可以寻址4GB的巨大RAM!即使到了今天,这对于绝大多数应用程序来说也足够了,Windows 32位实际上只允许您的应用程序在任何情况下都使用2GB的空间,而将其他2GB的空间保留给内核。
除少数例外,如果您的应用程序使用的内存超过2GB,则可能是您做错了什么。
例如,如果您要从数据库中拖回数百万行的数据,您是否真的需要将所有数据保存在RAM中?出于显示目的,即使您可以在屏幕上塞满所有的行,也没有人希望一次看到这几百万行,因此缓存到磁盘文件是一个更好的策略。本质上,绝大多数应用程序将使用2GB-4GB的可寻址RAM,因此这可能不是升级的理由。
速度呢?嗯,64位处理器实际上并没有比32位处理器快,它们的速度优势来自能够处理更大的整数。因此,如果您的应用程序需要处理大量数据,则升级到64位可能会提高性能,但是,如果您的代码尚未使用64位数值数据类型,则必须遍历所有代码并用64位等效项替换32位类型。为64位目标重新编译相同的应用程序不会削减它。
最终,根本没有充分的理由进行升级,并且请记住,因为所有指令操作数和编码都更大,所以64位可执行文件明显大于32位。进行跳转之前,请确保您需要64位。
Unicode迁移。
可怕的unicode迁移,似乎以某种方式使许多开发人员感到恐惧!实际上,Unicode并不像听起来那样可怕,在所有已迁移到unicode时代的编译器产品中,Delphi是最简单的产品之一。有些项目需要零更改,而编译器只需为您处理,而其他项目则可能需要一些更改,而一些项目则需要很多更改。
有一个工具(Unicode统计工具)可以帮助您确定需要进行的更改数量。您将此工具指向您的项目和单元文件,它将为您执行代码的统计分析,并为您提供所需工作量的度量。
在大多数情况下,编译器会强制转换字符串类型,以便您的代码继续按预期进行编译和运行。不正确的情况通常包括以下情形:
- 使用字符串存储二进制。在某些人看来,这似乎是个疯狂的主意,但Delphi的早期版本在二进制数据的存储(无字节数组)方面存在局限性,这使富有创造力的Delphi工程师采用了使用字符串存储二进制数据的选项。这种类型的代码应该早就被替换了,我的意思是,您已经花了二十年的时间来解决它!但是,您可能仍在使用执行此操作的代码,由于编译器不知道您在做什么,因此您现在不得不纠正它。编译器无法确定您是否滥用了字符串数据类型,因此这里无济于事。
- 序列化和反序列化。如果您的应用程序已将序列化的字符串(即逐个字节地将其传递到流中)存储在磁盘或数据库中,那么这些字符串在进行序列化时就是ANSI。将代码迁移到较新的Delphi编译器后,应用程序将尝试将文件中的字符串反序列化为UTF16-LE unicode字符串,其中每个字符的宽度为16位(保存一些32位的字符,但这是一个复杂性,值得更多阅读unicode)。因此,您的旧序列化数据无法反序列化。一种解决方案是将字符串作为字节数组读取,并将字节数组传递给现在已成为RTL一部分的许多unicode转换例程之一,以便将其从ANSI字符串转换为UTF16LE字符串。
- 调用较旧的API。Windows很久以前就采用unicode。升级Win32 API时,每个API调用的新版本都带有“ W”后缀,表示它们是调用的宽字符串版本。宽字符串是Windows使用的一种特殊的字符串类型,但是其中包含的数据本质上是UTF16-LE,与现在的Delphi默认字符串类型相同。无论如何,如果您将字符串(现在为UTF16)传递给较旧的基于ANSI的API调用,编译器可能会向您抱怨。在大多数情况下,编译器还会为您处理转换,但是会生成警告,以使您知道发生了这种情况,并且可能需要类型转换一个或两个参数。这将使您再次工作,但理想情况下,如果可用,则应迁移到API的Unicode形式。
- 在unicode下,某些控件的行为会有所不同!
您可能已经知道,大多数VCL控件都是Windows API提供的控件的包装。在将VCL迁移到Unicode的过程中,许多ANSI API调用被其备用Unicode感知等效项的调用所代替。我最近发现TRichEdit组件功能的'SelStart'和'SelLength'属性存在差异。与以前的unicode版本一样,现在不计入这些属性中的回车费。我在此处添加了博客文章,其中包含针对这些问题的一些解决方案:http : //chapmanworld/2015/11/04/trichedit-behaves-differently-under-unicode/
有关使用Delphi进行unicode迁移的更多详细信息(远远超出此处介绍的范围),可以在以下 网址找到:http://www.embarcadero/rad-in-action/migration-upgrade-center
实际数据类型。
在版本迁移的讨论中经常被忽略的是,旧的“真实”数据类型已从编译器中删除,并被替换为“双重”数据类型的别名。它经常被忽略的原因是它很少出现问题,但是,与unicode迁移一样,在反序列化由使用早期Delphi版本编译的应用程序序列化的数据时,这一小小的改变也可能引起人们的注意。如果在代码中使用实数,请抬头。
BDE不见了!
不要惊慌 BDE实际上还没有完全消失,但是已经过时了。默认情况下,BDE不再随Delphi一起提供,但是您可以在购买Delphi后从您的EDN帐户单独下载。原因是BDE很旧,缺乏unicode支持,并已被性能优越的FireDAC取代。
如果您的应用程序使用了BDE,建议您使用reFind工具将项目迁移到FireDAC。(使用reFind从BDE迁移到FireDAC / David I到FireDAC和Interbase的迁移 )该工具几乎可以为您完成工作!我还没有听说过任何实际遇到困难的人,因此,如果您遇到困难,尤其是找到解决方案,请考虑注册并在注释中留下注释!
还在使用paradox吗?
一些较旧的Delphi应用程序仍在使用paradox数据库。不幸的是,该数据库不再受支持,因此您可能不得不迁移到另一个数据库引擎。如果您只使用了paradox来满足数据库需求,那么您可能还想学习一点SQL和DDL,以便利用更现代的数据库。这样的学费超出了本页面的范围,但是,您会在网上找到一些出色的教程,老实说,这将是值得您花费的时间!
Marco Cantu从Paradox和dBase进行迁移。
W3Schools SQL教程。
第三方组件。
我为您保存了最好的直到最后!有些开发人员喜欢它们,有些则讨厌它们,但是在两所学校中,您可能都至少使用了某些第三方组件。不喜欢第三方组件的两个最大原因是:
- 供应商的问题。他们在提供更新,错误修复等方面可能不可靠,或者可能已经完全消失了。
- 组件问题。编写不当的组件可能会影响应用程序甚至Rad Studio IDE的稳定性。
但是,如果您仔细选择了供应商,您会发现一个出色的第三方组件集,需要经常维护,并且可以提供稳定的高质量组件,从而从根本上增强Rad Studio / Delphi的性能,进而提高您的产品质量。因此,我属于“爱情”类别!
不管您在哪方面,如果使用了第三方组件,在将项目从较早的Delphi版本迁移到新版本之前,都需要使用最新版本的组件。Embarcadero正在努力通过其新的GetIt功能来提供帮助,该功能提供了第三方组件存储库,可以在IDE内自动安装多个流行的组件集!
请参阅:RadStudio XE10.4.1获取组件存储库!
该存储库中的组件集合很小,但是正在增长,Embarcadero甚至资助了维护者已经离开或放弃其产品的通用组件集的更新。Embarcadero还确保存储库中的组件将使用最新的Delphi版本进行更新,因此无法找到自己以后不再设置该组件的位置。
在撰写本文时,GetIt存储库中安装的组件包括:
Abbrevia 10.0
AerServ 10.0
AsyncPro for VCL 1.0
Boos 1.39 / 1.55
Essentials TurboPack for VCL 1.0
ICS for FMX和VCL 8.16
Lockbox 2.0
Lockbox 3.5
现代化的AggPas VCL
OmniThread库3.04a
OnGuard for FMX 1.0
OnGuard for VCL 1.0
Orpheus for VCL 4.0.8
PowerPFD for VCL 1.0
适用
于VCL的SynEdit 1.0 SysTools 4.04
适用于VCL 5.5的VirtualTree
如果您尚未使用XE8,则还可以从此处获取XE7的以下几个组件: Romans Blog
如果不幸的是您不再拥有第三方组件,但是您明智地购买了源代码,那么更新该代码以在最新版本的Delphi中进行编译通常就比较简单了。例如,最近我发布了Advantage数据库组件的更新,因为SAP尚未针对Delphi XE8对其进行升级。我必须在代码中进行的唯一真正的更改就是更改条件定义以包括当前的编译器版本号,仅此而已!
另外,如果您曾经使用过开源的组件,但似乎已无法维护,则请务必查看GitHub,以查看该项目是否已迁移。其中很多都是没有警告或更新的。
最后,如果您拥有不再维护的第三方组件,并且您没有源代码,那么很抱歉,但是您不走运,这就是泰山老父强烈建议一定要使用带源码的第三方组件的原因。几十年来,一些组件公司已经离开了Delphi社区,这是不可避免的。如果要升级,则必须从其他供应商处找到等效的组件,然后修改代码以适合这些组件。
我的迁移需要多长时间?
它大约需要完成一半任务的两倍。抱歉,要迁移升级的项目千差万别。您可能没有碰到上述任何迁移陷阱,或者可能很不幸无法实现所有这些陷阱。
我的一些C ++客户报告说平均每天需要转换60,000行代码的旧版C ++ Builder项目。虽然C ++ Builder本身就是它自己的产品,但它也是基于VCL和FMX并经过unicode迁移的,因此这些数字可能是一个含糊的指南。确保使用上面链接的Unicode迁移统计工具,并且要保守但不要担心迁移。
结论。
如果这看起来像是一个冗长的页面,请记住,我已经谈到了本来可以忽略的跨平台迁移,并且我们正在讨论使用Delphi进行几十年版本的迁移。从一个版本到另一个版本,Delphi的断层很小,但是它是一种成熟的产品,必须与时俱进。
现代Delphi在IDE中具有很多功能(至少在我看来)是首屈一指的。它具有您期望的所有现代语言功能,并且能够在台式机,多层企业,云和移动开发空间中立于不败之地。如果您使用的不是最新版本,则会错过很多东西!希望您的迁移进展顺利。
谢谢阅读!Delphi万岁!!
版权声明:本文标题:将软件代码从Delphi 7迁移升级到Delphi 10.4.1等现代化新版本的注意事项 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729150191h1324067.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论