【问题标题】:Delphi Embarcadero XE: tons of warnings with String and PAnsiCharDelphi Embarcadero XE:大量使用 String 和 PAnsiChar 的警告
【发布时间】:2011-06-02 13:27:50
【问题描述】:

我正在尝试从 Delphi 2007 迁移到 Embarcadero RAD Studio XE。 我收到大量警告。 它们看起来都是这样的:我有一个声明“字符串”的过程:

procedure SendMail( ADestinataire,ASubject : String);

我正在尝试像这样调用 Windows API:

  Res := MAPIResolveName(Session, Application.Handle,
    PAnsiChar(ADestinataire), MAPI_LOGON_UI, 0, PRecip);

所以警告是:

W1044:将字符串转换为 PAnsiChar 可疑对象。

我做错了什么/我应该如何纠正这个(350 个警告...)?

非常感谢

【问题讨论】:

    标签: string delphi compiler-warnings delphi-xe


    【解决方案1】:

    MAPIResolveName 使用 LPSTR 参数,在 Delphi 中为 PAnsiChar。简单 MAPI 不支持 UTF16 字符串(尽管它可以与 UTF8 字符串一起使用),所以如果您坚持简单 MAPI,您应该使用 AnsiStrings,例如

    procedure SendMail( ADestinataire,ASubject : AnsiString);
    

    或者更好,你可以使用

    procedure SendMail( ADestinataire,ASubject : String);
    

    并在调用 MAPIResolveName 之前将字符串参数显式转换为 AnsiStrings


    更新 整个 Simple MAPI 现在已弃用;简单 MAPI 可以与 UTF8 字符串一起使用,但需要对 code and registry 进行一些更改。

    因此,如果问题是关于将旧的 ANSI Simple MAPI 快速移植到 Unicode Delphi,最好还是坚持 AnsiStrings。

    更可靠的方法是完全放弃 Simple MAPI 并改用 Extended MAPI

    【讨论】:

    • @Olivier Pons:如果它支持 UTF8 字符串,最好使用 AnsiString 的 UTF8 特化 - 方便地命名为 UTF8String。这样它是一个无损转换(Unicode 到 ANSI 是有损的。)
    • 非常感谢您的精彩回答。它不是专门关于 Simple MAPI(不幸的是我没有时间重写它),但一般来说,当访问 Windows API 和周围的所有东西时。如果我做对了,我可能必须将字符串参数转换为 AnsiStrings,而不是像 PChar(MyStringParam) 这样简单的东西。
    • @Olivier - 不,我的回答与一般的 Windows API 无关。大多数 Windows API 函数都有 unicode (UTF16) 变体,在升级到 Unicode Delphi 时,您应该遵循 Andreas Rejbrand 答案的第一部分。简单 MAPI 是规则中的一个例外 - 它没有 unicode (UTF16) 变体,因此您应该遵守 ANSI 字符串。
    【解决方案2】:

    随便写

    Res := MAPIResolveName(Session, Application.Handle,
      PChar(ADestinataire), MAPI_LOGON_UI, 0, PRecip);
    

    如果您有string,即Unicode 字符串,即指向Unicode 字符序列的指针,则不应将其转换为PAnsiCharPAnsiChar 是指向非 Unicode 字符序列的指针。实际上,转换为PSomethingChar 类型只是告诉编译器解释转换中的内容作为指定类型的指针。它不做任何转换。所以,基本上,现在你对编译器撒谎:你有一个 Unicode 字符串,并指示编译器将其解释为 ANSI(非 Unicode)字符串。这很糟糕。

    相反,您应该将其转换为 PWideChar,这是一个指向 Unicode 字符序列的指针。在 Delphi 2009+ 中,PChar 等同于 PWideChar

    当然,如果你向函数发送一个指向 Unicode 字符序列的指针,那么函数最好期待 Unicode 字符,但我不确定 MAPIResolveName 函数是否属于这种情况。我怀疑它实际上需要 ANSI(即非 Unicode)字符。如果是这种情况,您需要将 Unicode 字符串转换为 ANSI(非 Unicode)字符串。这很简单,只需写AnsiString(ADestinataire)。然后转换为 ANSI(非 Unicode)PAnsiChar:

    Res := MAPIResolveName(Session, Application.Handle,
      PANsiChar(AnsiString(ADestinataire)), MAPI_LOGON_UI, 0, PRecip);
    

    【讨论】:

      【解决方案3】:

      从 Delphi 2009 开始,字符串数据类型现在实现为 Unicode 字符串。以前的版本将字符串数据类型实现为 Ansi 字符串(即每个字符一个字节)。

      这在我们将 2007 年的应用程序移植到 XE 时产生了重大影响,这些文章非常有帮助:

      Delphi in a Unicode World(三部分中的第一部分)

      Delphi and Unicode

      Delphi Unicode Migration for Mere Mortals

      【讨论】:

        【解决方案4】:

        退一步:

        When using    use the cast
        ============  ================
        String        PChar
        AnsiString    PAnsiChar
        WideString    PWideChar
        

        String 曾经是AnsiString 的别名,这意味着如果您使用PAnsiChar(即使您应该使用PChar),它发生工作。

        现在stringUnicodeString 的别名,这意味着使用PAnsiChar(这一直是错误的)现在真的错了。

        知道了这个你就可以解决问题了:

        ADestinataire: String
        PAnsiChar(ADestinataire)
        

        【讨论】:

          猜你喜欢
          • 2011-05-31
          • 1970-01-01
          • 2011-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-29
          • 1970-01-01
          相关资源
          最近更新 更多