Delphi 2009/2010中新的字符串类型如何工作?

7
我需要将一个使用strings、AnsiStrings、WideStrings和UTF8数据的大型遗留应用程序转换为Delphi 2009,并且我很难理解新字符串类型的工作原理以及它们应该如何使用。该应用程序完全支持Unicode,使用了TntUnicodeControls,还有一些第三方DLL需要特定编码的字符串,主要是UTF8和UTF16,这使得转换任务不像人们想象的那么简单。
我特别遇到了C DLL调用的问题,选择正确的类型也很麻烦。我也发现有很多隐式的字符串转换,因为其中一个DLL似乎总是接收UTF-8编码的字符串,无论Delphi字符串的编码方式如何。
请问有人可以提供一份关于新的Delphi 2009字符串类型——UnicodeString和RawByteString的简要概述,可能会有一些使用提示和在转换pre 2009应用程序时可能遇到的问题吗?

CodeRage 4的重播已经上线,请访问http://www.delphifeeds.com/go/s/60421和http://conferences.embarcadero.com/coderage/sessions。 - Jeroen Wiert Pluimers
5个回答

11

请查看由Marco Cantù撰写的白皮书Delphi和Unicode,以及我猜是Joel所写的每个软件开发人员都必须绝对、肯定地了解Unicode和字符集的最低限度(没有任何借口!)

一个陷阱是,默认的Win32 API调用已被映射为使用W(宽字符串)版本,而不是A(ANSI)版本,例如ShellExecuteA。如果您的代码正在做内部布局假设AnsiString的棘手指针代码,那么它将会中断。一种备选方案是将PChar替换为PAnsiCharChar替换为AnsiCharstring替换为AnsiString,并在Win32 API调用的这部分代码末尾添加A。在代码实际编译和正常运行之后,您可以重构您的代码,使用stringUnicodeString)。


我曾经问过一个类似的问题,关于升级C++Builder 2007应用程序。其中并非所有内容都适用于你,但是一些链接和答案可能对你有用。 - David

8

本周五,您可以观看我的CodeRage 4关于“在程序中使用Unicode和其他编码”的演讲,或等待在线回放。

我将介绍一些编码并解释字符串格式。

幻灯片即将上线(我会尽快在网上发布),其中包含许多参考资料,您应该在互联网上阅读(但我必须承认我忘记了eed3si9n发布的有关Unicode的Joel链接)。

今天我会编辑这个答案并上传链接。


编辑:

如果您有一个小样例,可以展示您的C / C ++ DLL接收到UTF8编码的字符串,但认为它们应该以其他方式编码,请将其发布(给我发电子邮件;几乎任何@符号之前都可以通过我的名字来找到我)。

现在可以下载会议材料,包括“在程序中使用Unicode和其他编码”会话。

以下是该会话的链接:

请阅读以下内容:

  1. Marco Cantu,白皮书“Delphi和Unicode
  2. Marco Cantu,演讲“Delphi和Unicode
  3. Nick Hodges,白皮书“在Unicode世界中的Delphi

相关的在线帮助主题:

  1. Delphi和C++Builder 2009的新功能
  2. 字符串类型:基本类型:ShortString、AnsiString、WideString、UnicodeString
  3. 字符串类型:Unicode(包括字符串类型的内部存储布局)
  4. 字符串类型:启用Unicode
  5. 字符串类型:RawByteString(CodePage为$ffff的AnsiString)
  6. 字符串类型:UTF8String(CodePage为65001的AnsiString)
  7. 字符串<->PChar转换:PChar基础知识
  8. 字符串<->PChar转换:返回PChar本地变量
  9. 字符串<->PChar转换:传递本地变量作为PChar

希望这些内容能够帮助您。如果还有问题,请发送邮件给我,我会尽力在此处扩展答案。


考虑到Unicode不是一种编码方式,这个标题有些奇怪。但是引用维基百科的话来说:“Unicode可以通过不同的字符编码实现。” - mghie
谢谢!我会尝试将所有内容重命名为“在程序中使用Unicode和选择文本/字符串编码”。 - Jeroen Wiert Pluimers
...或者使用“使用Unicode和其他编码”,这也可以。 - Tim Sullivan
感谢您提供的优质资源列表以及慷慨的帮助提供。但如果我还有疑问,我宁愿在这里询问,这样其他读者也可以从您的知识中受益。 :) - Daniel Rikowski
@Tim:"(使用Unicode)和(其他编码)"怎么会没问题呢,这不就像"(吃苹果)和(其他种类的木头)"吗?难道英语真的那么不精确吗? - mghie
显示剩余4条评论

0
请注意,它不仅会命中真实的字符串代码,还会命中使用PCHAR遍历缓冲区或与API接口交互的代码。
例如,动态加载DLL的头文件初始化代码(getprocedureaddress/loadlibray)。

0

似乎我所有的问题都来自于赋值时的自动转换为UTF8String

我已经有了使用UTF8String的旧代码,只是为了帮助我思考变量应该包含哪种类型的字符串。

在开始移植我的应用程序时,出于同样的原因,我将AnsiString替换为UTF8String,但是代码依赖于UTF8String仅仅是(classic)AnsiString的别名。

现在,由于自动转换,这个假设不再成立,这就造成了许多问题。

如果您从2009年之前的Delphi代码移植时使用UTF8String,请小心!


0
在不同版本的Delphi或C++ Builder构建的dll之间传递字符串时需要注意另一件事情是,从2009年开始,AnsiStringBase的StrRec部分增加了两个额外的字段;codePage和elemSize。它们每个都是2个字节(short int),因此StrRec的大小现在为12个字节而不是8个字节。即使字符串的数据部分似乎传输正常,这可能会导致内存分配和销毁时出现无效指针异常问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接