質問

フォーマット引数Args形式関数に渡したい。 その例をいくつか見つけましたが、で文字列定数の割り当て方法は見つかりませんでした。TVERREC メンバー。次のコードは、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;
.

誰かが私にtvarrecメンバーに文字列(またはAnSistring)を定数の設定する方法を教えてください。私はDelphi 2009を使っています。

たくさんありがとう

役に立ちましたか?

解決

This seems to work in 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;

他のヒント

Just my two cents. TOndrej's answer is correct, but I just wanted to emphasize some points. And comments are not a good place to do it.

Please be aware that the AnsiString must be referenced during all time TVarRec will be used.

For instance, if you write a function setting an array of TVarRec, you should ensure that you made a temporary copy of the AnsiString created within the function to a variable which will remain until all time the TVarRec array is used. Otherwise you may have some random access violation (not every time, but only when the MM reassign the ansistring memory).

For instance, the following code is incorrect:

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;

Because the AnsiString and UnicodeString temporary variables will be freed when the procedure ends, and Results[].VString will still point to those freed memory...

Using a class or a record with some temporary private string may do the trick:

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;

Of course, in your program you may have an already existing class. In this case, you would better use a method, and some private temporary strings. For the method to be multi-thread safe (i.e. re-entrant) you should provide the temporary strings as parameters...

I use this trick to have valid a dynamic array of TVarData containing some AnsiString content in a class. In fact, TVarData and TVarRec both uses such non referenced pointer to strings, which can be confusing.

Be aware that issues involving pointer(S) like statements can be difficult to track.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top