TVARREC에서 문자열 (또는 ansistring)을 상수 설정하는 방법은 무엇입니까?
-
15-11-2019 - |
문제
i generating 인수를 format 함수로 전달하고 싶습니다.
나는 그 예들이 몇 가지 예를 발견했지만, TVARREC 회원.Args
가있는 컴파일에 대해 다음 코드가 실패합니다.
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.