Как я могу изменить и вернуть переменную типа PChar в вызове функции - PullRequest
0 голосов
/ 16 сентября 2011

Мне нужно сохранить значение варианта (которое всегда возвращает строку) в переменной PChar, теперь я использую этот код

procedure VariantToPChar(v:variant; p : PChar);
Var
  s : String;      
begin
  s:=v;
  GetMem(p,Length(s)*Sizeof(Char));
  StrCopy(p, PChar(s));
end;

Но мне интересно, существует ли лучший способ

Ответы [ 3 ]

4 голосов
/ 16 сентября 2011

Вы действительно, действительно должны создать PChar?Как можно дольше я буду использовать Strings, и только если для внешней библиотеки (например, Windows API) требуется PChar, я буду его разыгрывать.

uses
  Variants;
var
  vText: Variant;
  sText: String;
begin
  vText := 'Hello world';
  // VarToStr() can handle also null values
  sText := VarToStr(vText);
  // If absolutely necessary, cast it to PChar()
  CallToExternalFunction(PChar(sText));

Делая так, вы можете избежать проблем с памятьюde) распределение, нулевые значения и символы Ansi / Unicode.Если внешняя функция хочет записать в строку, вы можете использовать SetLength() перед приведением.Может быть, статья Работа с PChar может дать вам несколько идей.

2 голосов
/ 16 сентября 2011

Обновление: вы действительно не должны этого делать или использовать этот код , так как вы, вероятно, будете поощрять людей писать код, который пропускает. Люди будут вызывать это и не смогут освободить память, так как не знают, что эта функция выделяет память.

Если вы хотите сохранить что-то в буфере размера PChar, и это значение все еще связано с p (указатель p изменен и отличается, когда вы возвращаетесь из процедуры), тогда вам нужно сделать параметр a var (по ссылке вместо по значению) параметр, подобный этому:

procedure AllocPCharBufFromVariant(v:variant; var p : PChar);
Var
  s : String;      
begin
  try
    s:=v;
    GetMem(p,(Length(s)+1)*Sizeof(Char)); // fixed to add 1 for the nul
    StrCopy(p, PChar(s));
  except
    on E:EVariantError do 
    begin
     p := nil;
    end;
  end;
end;

Я также показал выше обработку EVariantError, которую я решил обработать, возвращая nil в параметре p, но вы должны подумать о том, как вы хотите, чтобы он работал, и затем как-то с этим справиться.

Приведенный выше код также теряет память, что ужасно, поэтому я переименовал его в AllocPChar. Кажется, в вашем исходном коде так много проблем, что я не могу рекомендовать хороший способ сделать то, что похоже на огромную кучу плохих вещей, и выбранное вами имя является одним из самых ужасных вариантов.

По крайней мере, имя Alloc подсказывает мне, поэтому я думаю: «Лучше мне освободить это, когда я закончу».

1 голос
/ 16 сентября 2011

Я подозреваю, что только выражение

PChar(string(v))

сделает свое дело.

И память, используемая для хранения преобразованного содержимого строки, будет доступна в объеме этого кода (т.е. какДо тех пор, пока будет использоваться ссылка на string(v), поэтому вы можете использовать явную переменную string, чтобы гарантировать, что ваша PChar память все еще выделена).

...