mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 13:48:11 +02:00

the IInterface implementation to be XPCom-compatible --- Merging r15997 through r16179 into '.': U rtl/inc/variants.pp U rtl/inc/objpash.inc U rtl/inc/objpas.inc U rtl/objpas/classes/persist.inc U rtl/objpas/classes/compon.inc U rtl/objpas/classes/classesh.inc A tests/test/tconstref1.pp A tests/test/tconstref2.pp A tests/test/tconstref3.pp U tests/test/tinterface4.pp A tests/test/tconstref4.pp U tests/webtbs/tw10897.pp U tests/webtbs/tw4086.pp U tests/webtbs/tw15363.pp U tests/webtbs/tw2177.pp U tests/webtbs/tw16592.pp U tests/tbs/tb0546.pp U compiler/sparc/cpupara.pas U compiler/i386/cpupara.pas U compiler/pdecsub.pas U compiler/symdef.pas U compiler/powerpc/cpupara.pas U compiler/avr/cpupara.pas U compiler/browcol.pas U compiler/defcmp.pas U compiler/powerpc64/cpupara.pas U compiler/ncgrtti.pas U compiler/x86_64/cpupara.pas U compiler/opttail.pas U compiler/htypechk.pas U compiler/tokens.pas U compiler/objcutil.pas U compiler/ncal.pas U compiler/symtable.pas U compiler/symsym.pas U compiler/m68k/cpupara.pas U compiler/regvars.pas U compiler/arm/cpupara.pas U compiler/symconst.pas U compiler/mips/cpupara.pas U compiler/paramgr.pas U compiler/psub.pas U compiler/pdecvar.pas U compiler/dbgstabs.pas U compiler/options.pas U packages/fcl-fpcunit/src/testutils.pp git-svn-id: trunk@16180 -
259 lines
5.0 KiB
ObjectPascal
259 lines
5.0 KiB
ObjectPascal
{ test code based on code from ttp://www.geocities.com/svi37/cyber/delphi9/iimplementation.html }
|
|
{$ifdef fpc}
|
|
{$mode delphi}
|
|
{$endif fpc}
|
|
uses
|
|
sysutils;
|
|
|
|
type
|
|
IXInterface = interface(IUnknown)
|
|
['{713252E5-4636-11D5-B572-00AA00ACFD08}']
|
|
procedure XStaticMethod;
|
|
procedure XVirtualMethod;
|
|
end;
|
|
|
|
IYInterface = interface(IUnknown)
|
|
['{713252E6-4636-11D5-B572-00AA00ACFD08}']
|
|
procedure YMethod;
|
|
end;
|
|
|
|
IZInterface = interface(IUnknown)
|
|
['{713252E4-4636-11D5-B572-00AA00ACFD08}']
|
|
end;
|
|
|
|
|
|
type
|
|
TInnerObject = class(TAggregatedObject,IXInterface,IYInterface)
|
|
public
|
|
procedure XStaticMethod;
|
|
procedure XVirtualMethod; virtual;
|
|
procedure YMethod;
|
|
end;
|
|
|
|
TSpecialObject = class(TInnerObject,IXInterface,IYInterface)
|
|
public
|
|
procedure XStaticMethod;
|
|
procedure XVirtualMethod; override;
|
|
procedure YMethod;
|
|
end;
|
|
|
|
TFoo = class({!!!! IXInterface, }IYInterface,IZInterface)
|
|
private
|
|
FInnerX: TInnerObject;
|
|
protected
|
|
function QueryInterface(constref IID: TGUID; out Obj): HResult; virtual; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
|
function _AddRef: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
|
function _Release: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
|
|
function GetX: TInnerObject; virtual;
|
|
function GetY: IYInterface;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
//!!!! property InnerX: TInnerObject read GetX implements IXInterface;
|
|
property InnerY: IYInterface read GetY implements IYInterface;
|
|
end;
|
|
|
|
TBar = class(TFoo,{!!!!IXInterface,}IYInterface,IUnknown)
|
|
private
|
|
FX: TSpecialObject;
|
|
FY: IYInterface;
|
|
protected
|
|
function GetX: TInnerObject; override;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
property Y: IYInterface read FY implements IYInterface;
|
|
//!!!! property X: TSpecialObject read FX implements IXInterface;
|
|
end;
|
|
|
|
{ TFoo }
|
|
|
|
constructor TFoo.Create;
|
|
var
|
|
i: IZInterface;
|
|
begin
|
|
inherited;
|
|
i := self;
|
|
FInnerX := TInnerObject.Create(i); //interface inh. to IUnknown
|
|
end;
|
|
|
|
destructor TFoo.Destroy;
|
|
begin
|
|
WriteLn('TFoo.Destroy');
|
|
FInnerX.Free;
|
|
inherited;
|
|
end;
|
|
|
|
{ TFoo.IUnknown }
|
|
|
|
function TFoo._AddRef: Integer;
|
|
begin
|
|
result := -1;
|
|
end;
|
|
|
|
function TFoo._Release: Integer;
|
|
begin
|
|
result := -1;
|
|
end;
|
|
|
|
function TFoo.QueryInterface(constref IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
|
|
end;function TFoo.GetX: TInnerObject;
|
|
begin
|
|
result := FInnerX;
|
|
end;
|
|
|
|
{ TFoo.IUnknown }
|
|
|
|
|
|
function TFoo.GetY: IYInterface;
|
|
begin
|
|
result := FInnerX;
|
|
end;
|
|
|
|
{ TBar }
|
|
|
|
constructor TBar.Create;
|
|
begin
|
|
inherited;
|
|
FX := TSpecialObject.Create(Self); //explicit IUnknown
|
|
FY := FX;
|
|
end;
|
|
|
|
destructor TBar.Destroy;
|
|
begin
|
|
WriteLn('TBar.Destroy');
|
|
FY := nil;
|
|
FX.Free;
|
|
inherited;
|
|
end;
|
|
|
|
function TBar.GetX: TInnerObject;
|
|
begin
|
|
result := FX;
|
|
end;
|
|
|
|
|
|
{ TInnerObject }
|
|
|
|
procedure TInnerObject.XStaticMethod;
|
|
begin
|
|
WriteLn(Format(
|
|
'Calls TInnerObject.XStaticMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
procedure TInnerObject.XVirtualMethod;
|
|
begin
|
|
WriteLn(Format(
|
|
'Calls TInnerObject.XVirtualMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
|
|
procedure TInnerObject.YMethod;
|
|
begin
|
|
WriteLn(Format(
|
|
'Calls TInnerObject.YMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
{ TSpecialObject }
|
|
|
|
procedure TSpecialObject.XStaticMethod;
|
|
begin
|
|
WriteLn(Format(
|
|
'Calls TSpecialObject.XStaticMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
procedure TSpecialObject.XVirtualMethod;
|
|
begin
|
|
// inherited;
|
|
WriteLn(Format(
|
|
'Calls TSpecialObject.XVirtualMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
procedure TSpecialObject.YMethod;
|
|
begin
|
|
WriteLn(Format(
|
|
'Calls TSpecialObject.YMethod on a %s',[ClassName]));
|
|
end;
|
|
|
|
procedure TestFoo(AFoo: TFoo);
|
|
var
|
|
o: TFoo;
|
|
x: IXInterface;
|
|
y: IYInterface;
|
|
z: IZInterface;
|
|
begin
|
|
|
|
o := AFoo;
|
|
|
|
//!!!! x := o;
|
|
//!!!! x.XStaticMethod; // if AFoo is TBar TFoo.XStatic hides TBar.XStatic
|
|
//!!!! x.XVirtualMethod;
|
|
|
|
y := o;
|
|
y.YMethod;
|
|
|
|
//!!!! z := x as IZInterface;
|
|
z := y as IZInterface;
|
|
|
|
z := o;
|
|
//!!!! x := z as IXInterface;
|
|
|
|
end;
|
|
|
|
procedure TestBar(ABar: TBar);
|
|
var
|
|
o: TBar;
|
|
x: IXInterface;
|
|
y: IYInterface;
|
|
z: IZInterface;
|
|
begin
|
|
|
|
o := ABar;
|
|
|
|
//!!!! x := o;
|
|
//!!!! x.XStaticMethod;
|
|
//!!!! x.XVirtualMethod;
|
|
|
|
y := o;
|
|
y.YMethod;
|
|
|
|
//!!!! z := x as IZInterface;
|
|
z := y as IZInterface;
|
|
|
|
z := o;
|
|
//!!!! x := z as IXInterface;
|
|
|
|
end;
|
|
|
|
procedure Test;
|
|
var
|
|
AFoo: TFoo;
|
|
ABar: TBar;
|
|
begin
|
|
AFoo := TFoo.Create;
|
|
ABar := TBar.Create;
|
|
|
|
WriteLn('***TestFoo(AFoo)*****************');
|
|
TestFoo(AFoo);
|
|
|
|
WriteLn('***TestFoo(ABar)*****************');
|
|
TestFoo(ABar);
|
|
|
|
WriteLn('***TestBar(ABar)*****************');
|
|
TestBar(ABar);
|
|
|
|
AFoo.Free;
|
|
ABar.Free;
|
|
end;
|
|
|
|
|
|
begin
|
|
WriteLn('IntGetter.TInnerObject.InstanceSize: ',TInnerObject.InstanceSize);
|
|
WriteLn('IntGetter.TSpecialObject.InstanceSize: ',TSpecialObject.InstanceSize);
|
|
WriteLn('IntGetter.TFoo.InstanceSize: ',TFoo.InstanceSize);
|
|
WriteLn('IntGetter.TBar.InstanceSize: ',TBar.InstanceSize);
|
|
Test;
|
|
end.
|