如何在函数调用中修改和返回PChar类型的变量



我需要存储一个变量值(总是返回一个字符串)在PChar变量现在我使用这个代码

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

但是我想知道是否存在更好的方法

你真的需要创建一个PChar吗?只要可能,我会使用string,并且只有当外部库(如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可以给你一些想法。

更新:您真的不应该这样做或使用此代码,因为您可能会鼓励人们编写泄漏的代码。由于不知道这个函数会分配内存,所以人们调用这个函数时无法释放内存。

如果你想在PChar大小的缓冲区中存储一些东西,并且让该值仍然与p相关联(指针p被修改,当你从过程返回时是不同的),那么你需要使参数成为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,我选择通过在p参数中返回nil来处理它,但是您应该考虑如何工作,然后以某种方式处理它。

上面的代码也泄漏内存,这是可怕的,所以我重命名为AllocPChar。看起来你原来的代码有很多问题,我不能推荐一个好的方法来做一个看起来像一大堆糟糕的事情,你选择的名字是最糟糕的选择之一。

至少Alloc这个名字给了我一个提示,所以我在想"我最好在我完成它的时候释放它"。

我怀疑只是一个

PChar(string(v))

表达式就可以了。

和用于存储转换后的字符串内容的内存将在此代码的范围内可用(即只要string(v)将被引用-所以你可能想要使用显式的string变量来确保你的PChar内存仍然被分配)。

最新更新