Несовместимые типы PAnsiChar и PWideChar, поскольку StrAlloc возвращает PWideChar с StrAlloc

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

У меня есть этот код:

pcBuffer := StrAlloc(Stream.Size + 1) where pcBuffer is defined as PWideChar

Компонент хочет pcBuffer as PAnsiChar сейчас, поэтому, если я это сделаю, я получу ошибку для

StrAlloc — несовместимые типы PAnsiChar и PWideChar

так как StrAlloc возвращает PWideChar

Как мне это решить?

Могу ли я просто ввести преобразование в PAnsiChar or alloacate в формате Unicode или через GetMem?


person Shanand c    schedule 10.09.2014    source источник


Ответы (2)


В Delphi XE модуль SysUtils определяет следующие функции:

function AnsiStrAlloc(Size: Cardinal): PAnsiChar;
function WideStrAlloc(Size: Cardinal): PWideChar;
function StrAlloc(Size: Cardinal): PChar;

Вы должны позвонить AnsiStrAlloc, чтобы выделить PAnsiChar. Это получает Size, измеренное в символах. Вы должны учитывать нуль-терминатор.

var
  pcBuffer: PAnsiChar;
....
pcBuffer := AnsiStrAlloc(Stream.Size + 1);

Однако эти функции следует считать устаревшими. Они задокументированы как таковые в более поздних версиях Delphi. Вместо этого вам, вероятно, следует использовать AnsiString и позволить компилятору управлять временем жизни и распределением памяти.

var
  str: AnsiString;
  pcBuffer: PAnsiChar;
....
SetLength(str, Stream.Size);
pcBuffer := PAnsiChar(str);

Время жизни буфера управляется компилятором, как и в случае любой строковой переменной Delphi.

Вполне возможно, что приведенный выше код — не лучший способ решить вашу проблему. Не видя более подробной информации, трудно сказать наверняка, какое решение является лучшим. Единственное, в чем я достаточно уверен, так это в том, что StrAlloc и друзья - это не путь вперед.

person David Heffernan    schedule 10.09.2014
comment
@Shanand Удалите строку, позволив ей покинуть область действия, или установив для нее значение '', или вызвав Finalize и т. д. Очевидно, используйте любые функции, которые вы выберете, даже устаревшие, если вы выберете. Странно, что вы принимаете ответ, который кажется неверным, хотя и в деталях, и упоминаете код, который не будет компилироваться в XE, помеченной версии. Вы не используете XE, не так ли? Ваш комментарий очень сбивает с толку. Разочаровывает приложить усилия, чтобы ответить, и обнаружить, что в вопросе неправильные важные детали. Я уверен, что Реми со временем исправит код в своем ответе. - person David Heffernan; 10.09.2014
comment
Дэвид: Извинения.. неправильно отметил неправильный ответ.. но я, по крайней мере, сузил проблему до использования - AnsiStrings.AnsiStrAlloc(Stream.Size + 1), как было предложено remy; который потом был вами исправлен. Поскольку вы прокомментировали Реми, я отметил это. Скорее, я был доволен вашим ответом на его комментарий, который сработал для меня. Мой вопрос, я думаю, был довольно ясен, когда вы правильно ответили: «Спасибо за вашу помощь!» В будущем обязательно понадобится ваша помощь. - person Shanand c; 11.09.2014
comment
Существующий код в D2007, нужно переписать эту строку в XE6 (это был вопрос). В любом случае - это решено, и я занимаюсь другими проблемами. Спасибо, Дэвид и Реми. - person Shanand c; 11.09.2014

Вы вызываете StrAlloc() из блока SysUtils, который выделяет PWideChar.

Чтобы вместо этого выделить PAnsiChar, вызовите StrAlloc() из блока AnsiStrings:

uses
  ..., AnsiStrings;

pcBuffer := AnsiStrings.StrAlloc(Stream.Size + 1);
person Remy Lebeau    schedule 10.09.2014
comment
Насколько я могу судить, никогда не существовало ничего с именем AnsiStrings.StrAlloc. Вы, вероятно, думаете о AnsiStrings.AnsiStrAlloc. Но вопрос помечен как XE, и в этом случае даже AnsiStrings.AnsiStrAlloc не существует. В XE это функция SysUtils.AnsiStrAlloc. - person David Heffernan; 10.09.2014