3

我公司的主要应用程序主要是用 C++ 编写的(带有一些 Delphi 代码和组件)。我们将从 RAD Studio 2007 升级到 2010 的下一个版本,大约一周后开始。为了确保升级顺利进行,我需要了解什么?

目前我想到的几点是:

  • 统一码。这个看起来真的很复杂。我们的应用程序包含了 std::string-s 和 AnsiString-s 的可怕组合,以及它们之间的强制转换。我对此有很多问题,例如“wstring 是否能够保存 UnicodeString 可以保存的所有内容,我们是否应该只进行搜索/替换”,或者“我们是否应该完全避免所有 C++ 字符串类型并使用 UnicodeString”,“我们可以将所有事件处理程序更改为使用 String,尽管现有的.HPPs事件处理程序方法原型被编译器转换为 AnsiString”,一直到诸如“我们应该在所有字符串前面加上 L 前缀,还是编译器足够聪明并启用 Unicode 以使用Unicode 字符串”等。对此的任何见解将不胜感激。

    我们还需要向后兼容。我们的应用程序使用自己的二进制元组格式,当前将字符串存储为字节数组。我需要升级它以读取旧文件,并且大概还要编写新的 Unicode 字符串。如何处理以二进制格式嵌入的 Unicode 字符串?是否有任何通用方法可以将 UnicodeString 指向一个字节数组,这些字节最初可能写为 ANSI 字节或 Unicode,它会弄清楚它们是什么?

  • 第三方组件。我们主要使用SpTBX,它似乎是兼容的。

  • 项目升级。Codegear 论坛中的标准建议似乎是在升级时手动重新创建所有项目文件。这是一项非常大量的工作(我们的主应用程序中有 7 个项目(主要是库),外加六个 DLL,大量文件。)有什么方法可以自动执行此操作吗?

  • 链接器的外观如何?传统上,我们在链接器随机崩溃或资源耗尽时遇到了很多麻烦,尽管在 2007 年它变得更好了。这是我们的主应用程序被拆分为多个库的原因之一 - 链接器不能(希望,“不能,但现在可以“?)以其他方式处理它。

  • 我知道有一个新的类型库编辑器和格式(它存储 IDL,即文本,并动态生成 TLB?)这如何处理使用 TLB 升级现有 COM 项目?我们有内置在 C++ 应用程序中的 Delphi 代码和 TLB。

  • 还有什么我应该考虑或注意的吗?

我已经找到:

4

4 回答 4

4

项目升级。Codegear 论坛中的标准建议似乎是在升级时手动重新创建所有项目文件。这是一项非常大量的工作(我们的主应用程序中有 7 个项目(主要是库),外加六个 DLL,大量文件。)有什么方法可以自动执行此操作吗?

有:只需使用 IDE 的项目导入器 :)
说真的,我会尝试导入项目,然后去调查它是否似乎不起作用。

链接器的外观如何?传统上,我们在链接器随机崩溃或资源耗尽时遇到了很多麻烦,尽管在 2007 年它变得更好了。这是我们的主应用程序被拆分为多个库的原因之一 - 链接器不能(希望,“不能,但现在可以“?)以其他方式处理它。

自 C++Builder 2009 以来,我在使用 ILINK 时几乎没有遇到任何问题。我偶尔会读到其他人遇到内存不足错误,但新闻组中的某个人发现了一种解决方法:

https://forums.embarcadero.com/thread.jspa?messageID=140012&tstart=0#140012

此外,正如您可以在此处阅读的,编译器有一个新选项 (-Cx) 来控制它分配的最大内存量。

我知道有一个新的类型库编辑器和格式(它存储 IDL,即文本,并动态生成 TLB?)这如何处理使用 TLB 升级现有 COM 项目?

应该可以顺利工作。

我对此有很多疑问,例如“wstring 是否能够保存 UnicodeString 可以保存的所有内容,我们是否应该只进行搜索/替换”

是的,在 Windows 平台上 wchar_t 通常是 16 位大,这意味着它足以容纳 UnicodeString 所代表的 UTF-16。

或“我们是否应该完全避免所有 C++ 字符串类型并使用 UnicodeString”

取决于您的代码需要的可移植性。无论如何,只要你只需要一个字符串类型,就使用“String”,而不是“UnicodeString”。

“尽管现有的 .HPP 被编译器转换为 AnsiString,但我们能否将所有事件处理程序更改为使用 String”

首先,您不应该重复使用旧版本 DCC 生成的 .hpp 文件!对于在 Delphi 中使用 String 类型的事件处理程序,您必须使用 UnicodeString。如上所述,只需使用“String”,您的代码将适用于 C++Builder 的 ANSI 和 Unicode 版本。

一直到基础知识,例如“我们是否应该在所有字符串前面加上 L,或者编译器是否足够聪明并启用了 Unicode 以使用 Unicode 字符串”

编译器不会转换您的字符串(它会与语言标准冲突),但 AnsiString 和 UnicodeString 都具有 char* 和 wchar_t* 字符串文字的复制构造函数重载。即,以下将起作用:

AnsiString as = L"foo";
UnicodeString us = "bar";

但是,不能以这种方式工作的是一大堆 printf()/scanf() 函数;AnsiString::sprintf() 采用 const char*,UnicodeString::sprintf() 采用 const wchar_t*。

如果您经常使用 sprintf(),您可能会发现我的 CbdeFormat 库很有用;只需阅读我关于该主题的文章

于 2009-09-08T12:28:32.667 回答
2

您没有说二进制元组格式中的数据字符串是做什么用的:它们是否有必要存储 Unicode?当我从 D2007 过渡到 D2009 时,我只能保留系统 ANSI 字符串的某些部分。

如果需要存储 Unicode,那么您需要检查您现有的数据是否与 UTF-8 等格式兼容。如果存储在现有数据文件中的值范围存在问题,那么我会让您的下一次升级对任何旧数据文件进行一次性转换,读入旧 AnsiString 数据并将其作为 UTF-8 写回另一个文件名或扩展名,或通过修改适当的文件头数据。我已经对数据文件进行了很长时间的版本控制,只是为了允许这种处理更改。

我刚刚开始一个 BCB2010 项目,因此无法评论您的其他问题,但我当然很难将 Delphi 项目从 D2007 升级到 D2009 - 尽管我能够通过编辑项目文件来解决这个问题,这只是 XML。

祝你转换好运;-)

于 2009-09-08T09:02:11.013 回答
2

统一码。这个看起来真的很复杂。我们的应用程序包含了 std::string-s 和 AnsiString-s 的可怕组合,以及它们之间的强制转换。我对此有很多疑问,例如“wstring 是否能够保存 UnicodeString 可以保存的所有内容,我们是否应该只进行搜索/替换”

std::wstring包含wchar_t*字符串,就像一样System::UnicodeString

我们是否应该完全避免所有 C++ 字符串类型并使用 UnicodeString

这由您决定。 char*仍然支持字符串。您不必将所有内容都迁移到 Unicode。

尽管现有的 .HPP 被编译器转换为 AnsiString,但我们能否将所有事件处理程序更改为使用 String

不,您不能将自动管理的事件处理程序更改为使用System::String别名。所有 IDE 版本都会抱怨这一点。您将不得不手动更新您的事件处理程序声明和实现,以在适当的时候使用UnicodeString参数而不是AnsiString参数。这也意味着您也不能在多个 IDE 版本之间共享 DFM 和 Unit .h 文件(无论如何您都不应该这样做)。

我们应该在所有字符串前面加上 L,还是编译器足够聪明并启用了 Unicode 以使用 Unicode 字符串

不可以。如果你声明一个字符串常量或字符常量没有 L 前缀,数据仍将被解释为 Ansi。这并没有改变。但是,您可以将 Ansi 数据传递给System::UnicodeString(但不能传递给std::wstring),它会自动转换为 Unicode。但是您必须小心,因为它将使用操作系统的默认 Ansi 代码页来解释数据。只要您的 Ansi 数据仅使用 ASCII 字符,就可以了。否则,如果您使用的是非 ASCII 字符,那么您最好将数据放入已分配正确代码页的System::AnsiStringTor (两者均在 CB2009 中引入),然后将其分配给您的变量。将使用关联的代码页而不是操作系统默认代码页进行转换。System::RawByteStringSystem::UnicodeString

我们还需要向后兼容。我们的应用程序使用自己的二进制元组格式,当前将字符串存储为字节数组。我需要升级它以读取旧文件,并且大概还要编写新的 Unicode 字符串。如何处理以二进制格式嵌入的 Unicode 字符串?

如果您的元组需要 8 位字符,那么您必须确保任何结构声明等都是使用char而不是wchar_t字符。如果您需要存储 Unicode 字符串,但需要保持 8 位兼容性,那么您应该先将您的 Unicode 字符串编码为 UTF-8(您可以使用System::UTF8String字符串类型来帮助您 - 从 CB2009 开始,它是真正的 UTF -8 字符串现在)。只要您不使用非 ASCII 字符,那么您的旧应用程序就不会知道其中的区别,因为 ASCII 字符在 UTF-8 中按原样编码。但是,如果您想存储原始 Unicode 数据,那么您的元组将需要一个标志(如果它还没有)指示字符串数据是存储为 Ansi 还是 Unicode,并且您的应用程序必须查找该标志.

是否有任何通用方法可以将 UnicodeString 指向一个字节数组,这些字节最初可能写为 ANSI 字节或 Unicode,它会弄清楚它们是什么?

不,您必须事先知道字节的实际编码。如果将内存地址传递给System::AnsiStringor std::string,它将假定 Ansi 字符。如果您将相同的内存地址传递给System::UnicodeStringor std::wstring,它将假定为 Unicode 字符。

第三方组件。我们主要使用SpTBX,它似乎是兼容的。

就像所有以前的版本一样(除了从 2006 到 2007 的迁移),您拥有的任何第三方组件都需要为 2010 重新编译,或者手动(如果您有它们的源代码)或通过它们各自供应商。

项目升级。Codegear 论坛中的标准建议似乎是在升级时手动重新创建所有项目文件。

是的。这仍然适用。

我知道有一个新的类型库编辑器和格式(它存储 IDL,即文本,并动态生成 TLB?)

.TLB 文件根本不再使用。新系统现在可以在 .ridl(简化的 IDL)文件上运行。在编译期间,.ridl 直接在可执行文件的二进制资源中生成正确的 TypeLibrary 信息。不会生成 .tlb 文件。

这对使用 TLB 升级现有 COM 项目的处理效果如何?我们有内置在 C++ 应用程序中的 Delphi 代码和 TLB。

我不记得 CB2010(或 CB2009,就此而言)是否可以直接使用预先存在的 .tlb 文件。我不认为他们可以。但是,您可以通过 tlibimp.exe 运行 .tlb 文件,它将导出一个 .ridl 文件。或者,您可以从过去版本的 TLB 编辑器中复制 IDL 文本,然后手动将其粘贴到新的 .ridl 文件中。无论哪种方式,您都可以将该 .ridl 文件添加到您的 CB2010 项目中。

2007 年和 2010 年并存。我不确定我是否相信这个答案,因为我之前在同一台机器上遇到过 2006 和 2007 的问题。

这就是为什么我在同一台物理机上安装多个 IDE 版本时使用虚拟机的原因。

于 2009-09-08T22:10:27.357 回答
1

升级成本是否与收益相符?

为什么不开始逐步升级,在新平台上开发新组件。通过不同的互操作助手将新组件集成到旧版本。

vb6正在考虑升级到vb.net.

于 2009-09-08T07:44:40.847 回答