开发者

Delphi Embarcadero XE: tons of warnings with String and PAnsiChar

I'm trying to migrate from Delphi 2007 to Embarcadero RAD Studio XE. I'm getting tons of warnings. They all look like this: I have a procedure where I declare a "String":

procedure SendMail( ADestinataire,ASubject : String);

And I'm trying to call Windows API like:

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

So the warnings are:

W开发者_StackOverflow1044: Transtyping string into PAnsiChar suspect.

What am I doing wrong / how should I correct this (350 warnings...)?

Thank you very much


MAPIResolveName uses LPSTR parameter, which is PAnsiChar in Delphi. Simple MAPI does not support UTF16 strings (though it can be used with UTF8 strings), so if you adhere to simple MAPI you should use AnsiStrings, for example

procedure SendMail( ADestinataire,ASubject : AnsiString);

or better you can use

procedure SendMail( ADestinataire,ASubject : String);

and explicitly convert string parameters to AnsiStrings prior to calling MAPIResolveName


Update The whole Simple MAPI is now deprecated; Simple MAPI can be used with UTF8 strings, but it requires some changes in code and registry.

So if the question is about quick porting old ANSI Simple MAPI to Unicode Delphi, the best is to adhere to AnsiStrings.

A more solid approach is to abandon Simple MAPI completely and use Extended MAPI instead.


Just write

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

If you have a string, that is, a Unicode string, that is, a pointer to a sequence of Unicode characters, you shouldn't cast it to PAnsiChar. PAnsiChar is a pointer to a sequence of non-Unicode characters. Indeed, a cast to a PSomethingChar type simply tells the compiler to interpret the thing inside the cast as a pointer of the specified type. It doesn't do any conversion. So, basically, right now you lie to the compiler: You have a Unicode string and instructs the compiler to interpret it as an ANSI (non-Unicode) string. That's bad.

Instead, you should cast it to PWideChar, a pointer to a sequence of Unicode characters. In Delphi 2009+, PChar is equivalent to PWideChar.

Of course, if you send a pointer to a sequence of Unicode characters to the function, then the function had better expect Unicode characters, but I am not sure if this is the case of the MAPIResolveName function. I suspect that it actually requires ANSI (that is, non-Unicode) characters. If this is the case, you need to convert the Unicode string to an ANSI (non-Unicode) string. This is easy, just write AnsiString(ADestinataire). Then you cast to a ANSI (non-Unicode) PAnsiChar:

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


Starting with Delphi 2009, the string data type is now implemented as a Unicode string. Previous versions implemented the string data type as an Ansi string (i.e. one byte per character).

This had significant implications when we ported our apps from 2007 to XE, and these article were very helpful:

Delphi in a Unicode World (first of three parts)

Delphi and Unicode

Delphi Unicode Migration for Mere Mortals


To step back a moment:

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

String used to be an alias for AnsiString, which means it happened to work if you used PAnsiChar (even though you should have used PChar).

Now string is an alias for UnicodeString, which means using PAnsiChar (which was always wrong) is now really wrong.

Knowing this you can solve the question:

ADestinataire: String
PAnsiChar(ADestinataire)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜