tcustomvar1.pp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. program tcustomvar1;
  2. {$APPTYPE CONSOLE}
  3. {$MODE Delphi}
  4. uses
  5. Variants, SysUtils;
  6. type
  7. TSampleVariant = class(TCustomVariantType)
  8. protected
  9. procedure DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer); override;
  10. public
  11. procedure Clear(var V: TVarData); override;
  12. procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean ); override;
  13. end;
  14. procedure TSampleVariant.Clear(var V: TVarData);
  15. begin
  16. V.VType:=varEmpty;
  17. end;
  18. procedure TSampleVariant.Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean);
  19. begin
  20. if Indirect and VarDataIsByRef(Source) then
  21. VarDataCopyNoInd(Dest, Source)
  22. else with Dest do
  23. VType:=Source.VType;
  24. end;
  25. var
  26. funcname: String;
  27. argnames: array of String;
  28. argtypes: array of Byte;
  29. argvalues: array of Variant;
  30. procedure TSampleVariant.DispInvoke(Dest: PVarData; var Source: TVarData; CallDesc: PCallDesc; Params: Pointer);
  31. var
  32. n: AnsiString;
  33. nptr: PChar;
  34. arg: Pointer;
  35. t: Byte;
  36. i: LongInt;
  37. v: Variant;
  38. begin
  39. nptr := PChar(@CallDesc^.argtypes[CallDesc^.argcount]);
  40. n := StrPas(nptr);
  41. if n <> funcname then begin
  42. Writeln('Func name: got: ', n, ', expected: ', funcname);
  43. Halt(1);
  44. end;
  45. if Length(argnames) <> CallDesc^.namedargcount then
  46. Halt(1);
  47. nptr := nptr + Length(n) + 1;
  48. arg := Params;
  49. for i := 0 to CallDesc^.namedargcount - 1 do begin
  50. n := StrPas(nptr);
  51. if n <> argnames[i] then begin
  52. Writeln('Arg ', i, ': got: ', n, ', expected: ', argnames[i]);
  53. Halt(1);
  54. end;
  55. if CallDesc^.argtypes[i] <> argtypes[i] then begin
  56. Writeln('Arg ', i, ' type: got: ', CallDesc^.ArgTypes[i], ', expected: ', argtypes[i]);
  57. Halt(1);
  58. end;
  59. t := argtypes[i] and $7f;
  60. if argtypes[i] and $80 <> 0 then begin
  61. TVarData(v).VType := t or varByRef;
  62. TVarData(v).VPointer := PPointer(arg)^;
  63. end else begin
  64. TVarData(v).VType := t;
  65. case t of
  66. varSingle,
  67. varSmallint,
  68. varInteger,
  69. varLongWord,
  70. varBoolean,
  71. varShortInt,
  72. varByte,
  73. varWord:
  74. TVarData(v).VInteger := PInteger(arg)^;
  75. else
  76. TVarData(v).VAny := PPointer(arg)^;
  77. end;
  78. end;
  79. if v <> argvalues[i] then begin
  80. Writeln('Arg ', i, ' value: got: ', String(v), ', expected: ', String(argvalues[i]));
  81. Halt(1);
  82. end;
  83. nptr := nptr + Length(n) + 1;
  84. arg := PByte(arg) + SizeOf(Pointer);
  85. { unset so that VarClear doesn't try to free the constant WideChar }
  86. TVarData(v).vtype:=varEmpty;
  87. end;
  88. end;
  89. function ConvertArgType(aType: Word): Byte;
  90. var
  91. ref: Boolean;
  92. begin
  93. ref := (aType and varByRef) <> 0;
  94. aType := aType and not varByRef;
  95. case aType of
  96. varString:
  97. Result := varOleStr;
  98. otherwise
  99. Result := aType;
  100. end;
  101. if ref then
  102. Result := Result or $80;
  103. end;
  104. var
  105. SampleVariant: TSampleVariant;
  106. v, v1: Variant;
  107. begin
  108. SampleVariant:=TSampleVariant.Create;
  109. TVarData(v).VType:=SampleVariant.VarType;
  110. funcname := 'SomeProc';
  111. SetLength(argnames, 0);
  112. v.SomeProc;
  113. funcname := 'SomeFunc';
  114. SetLength(argnames, 0);
  115. v1 := v.SomeFunc;
  116. funcname := 'Begin';
  117. SetLength(argnames, 2);
  118. SetLength(argtypes, 2);
  119. SetLength(argvalues, 2);
  120. { the parameters are passed right-to-left }
  121. argnames[1] := 'Date';
  122. argnames[0] := 'Foobar';
  123. argvalues[1] := 42;
  124. argvalues[0] := 'Hello';
  125. argtypes[1] := ConvertArgType(TVarData(argvalues[1]).VType);
  126. argtypes[0] := ConvertArgType(TVarData(argvalues[0]).VType);
  127. v.&Begin(Date:=42,Foobar:='Hello');
  128. funcname := '_';
  129. SetLength(argnames, 0);
  130. v._;
  131. writeln('ok');
  132. end.