[fpc-pascal] Interfaces via implements keyword

Denis Golovan d.golovan.ml at gmail.com
Sat Nov 28 11:39:22 CET 2009


Hi Andrew

On Thu, Nov 26, 2009 at 4:48 AM, Andrew Hall <andrew.hall at shaw.ca> wrote:

> 1) Always reference your host class through an interface you know will be
> implemented by the host class, therefore calling "as" from this interface
> will always find any of the interfaces your class may support.  The easie=
st
> would be to declare "I1: IUnknown" in the code below - I haven't tried it
> but that should work.
>

Yes. At first of this too.


>
> 2) Store the host class reference in the other classes that implement the
> host and provide an "Owner: IUnknown" property in your "child" implementi=
ng
> classes to allow you to cast to any interface supported by the host class:
> "I2 :=3D I1.Owner as IIntf2"
>
>
And that's my current solution for some classes :)


> PS - normally your host class would not support the interface you are usi=
ng
> "implements" to achieve...


Normally yes. Unfortunately it's not my case.


> therefore the confusing circumstances of your first example would not
> normally happen - you'd be more likely to see this second example which i=
s a
> little easier to decipher...
>
> Regards,
>
> Andrew Hall.


But I think I found a better solution. The only way that needed to be
changed is the way of QueryInterface works.
I just took the idea with Owner and redefined QueryInterface method to use
it. Like following:

  { TInterfacedObj }

  TInterfacedObj =3D class(TObject, IUnknown)
    private
      FOwner:TInterfacedObj;

      function GetInterface(const iid : tguid;out obj):longint;
    public
      function QueryInterface(const iid : tguid;out obj) :
longint;virtual;stdcall;
      function _AddRef : longint;stdcall;
      function _Release : longint;stdcall;

      constructor Create(Owner:TInterfacedObj);
  end;
  { TInterfacedObj }

  const Err =3D HResult($80004002);
  function TInterfacedObj.GetInterface(const iid: tguid; out obj): longint;
  begin
    if inherited GetInterface(IID, Obj) then
      Result:=3D0
    else
      Result:=3DErr;
  end;

  function TInterfacedObj.QueryInterface(const iid: tguid; out obj):
longint;stdcall;
  begin
    WriteLn('QueryInterface ', ClassName);

    if FOwner =3D nil then
      Result:=3DGetInterface(iid, obj)
      else
      begin
        Result:=3DFOwner.QueryInterface(iid, obj);

        //try to find interface in itself
        if Result =3D Err then
           Result:=3DGetInterface(iid, obj);
      end;
  end;

  constructor TInterfacedObj.Create(Owner: TInterfacedObj);
  begin
    FOwner:=3DOwner;
  end;

Now it is possible to start interface search from the owner and only if
owner has no appropriate interface, it queries itself.
That's seems pretty nice solution.


-- =

Best regards,
Denis Golovan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freepascal.org/lists/fpc-pascal/attachments/20091128/dae9=
b619/attachment.htm


More information about the fpc-pascal mailing list