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)
精彩评论