5

我想将格式化参数传递给ArgsFormat函数。我找到了一些例子,但我不知道如何在TVarRec成员中分配字符串常量。以下代码在编译时失败E2089 Invalid typecast

procedure TForm1.Button1Click(Sender: TObject);
var Arguments: array of TVarRec;
begin
  SetLength(Arguments, 2);

  Arguments[0].VInteger := 111;
  Arguments[1].VAnsiString :=  PAnsiString('Text'); // I want to set this member

  ShowMessage(Format('Decimal: %d, String: %s', Arguments));
end;

谁能建议我如何将字符串(或 AnsiString)常量设置为 TVarRec 成员?我正在使用德尔福 2009。

非常感谢

4

3 回答 3

10

这似乎在 XE 中有效:

var
  Args: array[0..1] of TVarRec;
  S: AnsiString;
  U: UnicodeString;
begin
  S := 'Hello';
  U := 'world';
  Args[0].VType := vtAnsiString;
  Args[0].VAnsiString := Pointer(S);
  Args[1].VType := vtUnicodeString;
  Args[1].VUnicodeString := Pointer(U);

  Writeln(Format('%s, %s!', Args));
end;
于 2011-05-19T13:15:24.677 回答
5

只是我的两分钱。TOndrej 的回答是正确的,但我只是想强调几点。评论不是一个好地方。

请注意,AnsiString在所有时间都必须引用的TVarRec将被使用。

例如,如果您编写一个设置数组的函数TVarRec,您应该确保AnsiString将函数中创建的临时副本复制到一个变量,该变量将一直保留到该TVarRec数组被使用为止。否则你可能会遇到一些随机访问冲突(不是每次,但只有当 MM 重新分配ansistring内存时)。

例如,以下代码不正确

type
  TVarRec2 = array[0..1] of TVarRec;

procedure SetVarRec(a,b: integer; var Result: TVarRec2);
begin
  Result[0].VType := vtAnsiString;
  Result[0].VString := pointer(AnsiString(IntToStr(a)));
  Result[1].VType := vtUnicodeString;
  Result[1].VString := pointer(UnicodeString(IntToStr(b)));
end;

因为AnsiStringUnicodeString临时变量将在过程结束时被释放,并且Results[].VString仍然指向那些释放的内存......

使用带有一些临时私有字符串的类或记录可以解决问题:

type
  TMyVar2 = record
  private
    tmpA: AnsiString;
    tmpB: UnicodeString; 
  public
    VarRec: TVarRec2;
    procedure SetVarRec(a,b: integer);
  end;

procedure TMyVar2.SetVarRec(a,b: integer);
begin
  VarRec[0].VType := vtAnsiString;
  tmpA := AnsiString(IntToStr(a));
  VarRec[0].VString := pointer(tmpA);
  VarRec[1].VType := vtUnicodeString;
  tmpB := UnicodeString(IntToStr(b));
  VarRec[1].VString := pointer(tmpB);
end;

当然,在您的程序中,您可能已经有一个类。在这种情况下,您最好使用方法和一些私有临时字符串。对于多线程安全的方法(即可重入),您应该提供临时字符串作为参数...

我使用这个技巧来获得一个TVarData包含类中某些AnsiString内容的有效动态数组。事实上,TVarData两者 TVarRec都使用这种指向字符串的非引用指针,这可能会造成混淆。

请注意,涉及pointer(S)类似语句的问题可能难以跟踪。

于 2011-05-19T14:46:03.507 回答
0

你必须使用 ansistring 值的数组,因为你必须使用点

temps: array of AnsiString;
value: array of TVarRec;
...
max_count := 10;
setlength(temps,max_count);
setlength(value,max_count);
for i := 0 to max_count-1 do begin
  temps[i] := IntToStr(i);
  value[i].VType := vtAnsiString;
  value[i].VString := Pointer(temps[i]); 
end;
AdoTable.insertrecord(value);
于 2021-07-02T01:13:58.127 回答