我需要存储一个变量值(总是返回一个字符串)在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
内存仍然被分配)。