Подтвердить что ты не робот

Преобразование строки в PAnsiChar в Delphi 2009

Я конвертирую свои приложения в Delphi 2009 и сталкиваюсь с интригующей проблемой с некоторыми вызовами, которым необходимо преобразовать строку (широко) в AnsiString.

Вот пример, чтобы продемонстрировать, что у меня есть проблема:

var
  s: PAnsiChar;

...

s := PAnsiChar(Application.ExeName);

В Delphi 2007 и предыдущих версиях s: = PChar (Application.ExeName) вернет путь EXE-приложения.

с Delphi 2009, s: = PAnsiChar (Application.ExeName) возвращает только "E".

Я предполагаю, что, поскольку я преобразовываю строку unicode в строку ansi, но как ее преобразовать, чтобы PAnsiChar получил полную строку?

4b9b3361

Ответ 1

У меня нет Delphi 2009 здесь, поэтому я не могу его проверить. Но, возможно, вам стоит попробовать:

s := PAnsiChar(AnsiString(Application.ExeName));

Как уже указывал gabr, это не очень хорошая практика, и вы будете использовать ее только в том случае, если вы на 100% уверены. Строка содержит только символы, которые имеют прямое сопоставление с диапазоном ANSI.

Вот почему вы должны получить предупреждение, потому что вы конвертируете Unicode в ANSI.

Ответ 2

Вместо использования типа String используйте RawByteString:

s: RawByteString;

s := LoadSomeRegularString(usually a string type);

PAnsiChar(s) <<< all fine.

Ответ 3

Работа с явным преобразованием Gamecat. Я объясняю проблему более подробно ниже, чтобы, возможно, кто-то мог указать на лучшее решение.

Я использую следующую функцию для получения даты компиляции приложения:

function LinkerTimeStamp(const FileName: string): TDateTime;
var
  LI: TLoadedImage;
begin
  {$IFDEF UNICODE}
  Win32Check(MapAndLoad(PAnsiChar(AnsiString(FileName)), nil, @LI, False, True));
  {$ELSE}
  Win32Check(MapAndLoad(PChar(FileName), nil, @LI, False, True));
  {$ENDIF}
  Result := LI.FileHeader.FileHeader.TimeDateStamp / SecsPerDay + UnixDateDelta;
  UnMapAndLoad(@LI);
end;

MapAndLoad требует PAnsiChar для параметра ImageName, поэтому мне нужно преобразовать строку юникода. Есть ли другая альтернатива, чтобы сначала преобразовать в AnsiString?

Ответ 4

У меня была такая же проблема. PAnsiChar указывает только на первый символ. Я написал следующую функцию для обработки старых функций.

// This function converts a string to a PAnsiChar
// If the output is not the same, an exception is raised
// Author: [email protected]

function StringToPAnsiChar(stringVar : string) : PAnsiChar;
Var
  AnsString : AnsiString;
  InternalError : Boolean;
begin
  InternalError := false;
  Result := '';
  try
    if stringVar <> '' Then
    begin
       AnsString := AnsiString(StringVar);
       Result := PAnsiChar(PAnsiString(AnsString));
    end;
  Except
    InternalError := true;
  end;
  if InternalError or (String(Result) <> stringVar) then
  begin
    Raise Exception.Create('Conversion from string to PAnsiChar failed!');
  end;
end;

Ответ 6

Я думаю, что ты немного ушел. Каждая функция Win32 API имеет юникодную копию, если она ожидает строку. Попробуйте MapAndLoadW вместо MapAndLoad...