program project1;
uses
TypInfo, SysUtils;
type
generic TCallProcStdCall<T> = procedure(aArg1:T;aArg2:Integer;aArg3:Integer) of object;stdcall;
generic TCallProcReg<T> = procedure(aArg1:T;aArg2:Integer;aArg3:Integer) of object;
TGenericCallProcIntegerStdCall = specialize TCallProcStdCall<Integer>;
TGenericCallProcIntegerReg = specialize TCallProcReg<Integer>;
TCallProcIntegerStdCall = procedure(aArg1:Integer;aArg2:Integer;aArg3:Integer) of object;stdcall;
{ TTest }
generic TGenericTest<T> = class
public
procedure StdCalling(aArg1:T;aArg2:Integer;aArg3:Integer);stdcall;
procedure RegCalling(aArg1:T;aArg2:Integer;aArg3:Integer);
end;
TIntTest = specialize TGenericTest<Integer>;
{ TTest }
procedure TGenericTest.StdCalling(aArg1:T;aArg2:Integer;aArg3:Integer); stdcall;
begin
WriteLn('Self=0x'+IntToHex(IntPtr(self),SizeOf(self)*2)+
' Arg1='+IntToStr(PtrInt(aArg1))+
' Arg2='+IntToStr(aArg2)+
' Arg3='+IntToStr(aArg3));
end;
procedure TGenericTest.RegCalling(aArg1:T;aArg2:Integer;aArg3:Integer);
begin
WriteLn('Self=0x'+IntToHex(IntPtr(self),SizeOf(self)*2)+
' Arg1='+IntToStr(PtrInt(aArg1))+
' Arg2='+IntToStr(aArg2)+
' Arg3='+IntToStr(aArg3));
end;
var
obj : TIntTest;
stdCallPtr: TGenericCallProcIntegerStdCall;
regCallPtr: TGenericCallProcIntegerReg;
begin
obj := TIntTest.Create;
try
//project1.lpr(51,23) Error:
//Incompatible types:
//got "<procedure variable type of procedure(LongInt;LongInt;LongInt) of object;StdCall>"
//expected "<procedure variable type of procedure(LongInt;LongInt;LongInt) of object;Register>"
//stdCallPtr := @obj.StdCalling;
stdCallPtr := TGenericCallProcIntegerStdCall(@obj.StdCalling);
regCallPtr := @obj.RegCalling;
obj.StdCalling(1,2,3);
obj.RegCalling(1,2,3);
//call is made with wrong calling convention
stdCallPtr(1,2,3);
regCallPtr(1,2,3);
//call is made with correct calling convention
TCallProcIntegerStdCall(stdCallPtr)(1,2,3);
readln;
finally
obj.Free;
end;
end.