Delphi Embarcadero XE: множество предупреждений с помощью String и PAnsiChar - PullRequest
1 голос
/ 02 июня 2011

Я пытаюсь перейти с Delphi 2007 на Embarcadero RAD Studio XE.Я получаю тонны предупреждений.Все они выглядят так: у меня есть процедура, в которой я объявляю «String»:

procedure SendMail( ADestinataire,ASubject : String);

И я пытаюсь вызвать Windows API как:

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

Итак, предупрежденияявляются:

W1044: передача строки в подозреваемого PAnsiChar.

Что я делаю неправильно / как мне исправить это (350 предупреждений ...)?

Большое спасибо

Ответы [ 4 ]

8 голосов
/ 02 июня 2011

MAPIResolveName использует параметр LPSTR, который является PAnsiChar в Delphi. Простой MAPI не поддерживает строки UTF16 (хотя он может использоваться со строками UTF8), поэтому, если вы придерживаетесь простого MAPI, вам следует использовать AnsiStrings, например

procedure SendMail( ADestinataire,ASubject : AnsiString);

или лучше, вы можете использовать

procedure SendMail( ADestinataire,ASubject : String);

и явное преобразование строковых параметров в AnsiStrings до вызова MAPIResolveName


Обновление Весь Simple MAPI теперь устарел; Простой MAPI может использоваться со строками UTF8, но требует некоторых изменений в коде и реестре .

Так что, если речь идет о быстром переносе старого ANSI Simple MAPI на Unicode Delphi, лучше всего придерживаться AnsiStrings.

Более надежный подход - полностью отказаться от Simple MAPI и использовать вместо него Extended MAPI .

2 голосов
/ 02 июня 2011

Просто напишите

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

Если у вас есть string, то есть строка Unicode, то есть указатель на последовательность символов Unicode, вы не должны приводить ее к PAnsiChar. PAnsiChar - указатель на последовательность символов, отличных от Юникода. Действительно, приведение к типу PSomethingChar просто указывает компилятору интерпретировать вещь внутри преобразования как указатель указанного типа. Это не делает никакого преобразования. Итак, в основном, сейчас вы лжете компилятору: у вас есть строка Unicode и выдает команду компилятору интерпретировать ее как строку ANSI (не-Unicode). Это плохо.

Вместо этого вы должны привести его к PWideChar, указателю на последовательность символов Юникода. В Delphi 2009+ PChar эквивалентно PWideChar.

Конечно, если вы отправляете указатель на последовательность символов Unicode для функции, то функции лучше ожидать символы Unicode, но я не уверен, что это случай функции MAPIResolveName. Я подозреваю, что это на самом деле требует ANSI (то есть, не Unicode) символов. В этом случае вам необходимо преобразовать строку Unicode в строку ANSI (не Unicode). Это легко, просто напишите AnsiString(ADestinataire). Затем вы применяете ANSI (не в Юникоде) PAnsiChar:

Res := MAPIResolveName(Session, Application.Handle,
  PANsiChar(AnsiString(ADestinataire)), MAPI_LOGON_UI, 0, PRecip);
1 голос
/ 02 июня 2011

Начиная с Delphi 2009, строковый тип данных теперь реализован в виде строки Unicode.Предыдущие версии реализовывали строковый тип данных как строку Ansi (т. Е. Один байт на символ).

Это имело значительные последствия, когда мы портировали наши приложения с 2007 года на XE, и эти статьи были очень полезны:

Delphi в мире Unicode (первая из трех частей)

Delphi и Unicode

Миграция Delphi Unicode для простых смертных

0 голосов
/ 12 июня 2011

Чтобы сделать шаг назад:

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

String раньше был псевдонимом для AnsiString, что означает, что произошло для работы, если вы использовали PAnsiChar (даже если вы должны были использовать PChar).

Теперь string является псевдонимом для UnicodeString, что означает, что использование PAnsiChar (что всегда было неправильно) теперь действительно неправильно.

Зная это, вы можете решить вопрос:

ADestinataire: String
PAnsiChar(ADestinataire)
...