[fpc-pascal] Question about interfaces and patch
ml at brainwashers.org
ml at brainwashers.org
Wed Mar 23 15:51:43 CET 2005
Quoting Marco van de Voort <marcov at stack.nl>:
> > On Tue, 22 Mar 2005, ml wrote:
> > > // than one interface
> > > a := (object as IA); // correct
> > > b := (object as IB); // returns pointer to the first interface
vmt=IA
> > > c := (object as IC); // returns pointer to the first interface
vmt=IA
> > > // there's no way to do again it's like direct call to exception
> > > obj := a; // returns pointer(obj) + 12 ???
> >
> > This is nonsense. You cannot assign an interface to a class.
> > A class IMPLEMENTS an interface, it is not an interface.
Ok, its nonsense. I said it already works with my patch, but I guess you
know it better. So my example down there doesn't work (with patch). You
should know.
I (; can't ;) transfer from one interface to other back to object and to
3rd interface. I just imagine my results.
>
> Ml, see my original message. If you have an interface, you know
nothing of
> the stuff the class adds outside that interface.
>
Wrong. 10 minutes (looking trough sources, seeing where the problem is
and implementing my patch) and everything worked.
Getting Me: TObject enables you to call all class functions. So you can
compare class compatibility or anything (directly from interface).
My implementation works ok, I was just worried a little about
implementation (I wouldn't want to break any COM interface, I'm not a
windows person and I just wanted to ask for wished approach on as and
operators and one more or less cosmetic approach, as I said I'm not
using windows and I wouldn't want to break anything). In Linux this
patch breaks nothing and adds 0 changes to previous sources that used
interfaces. The only added function Me is already solved and that's all.
But my best guess is that you're not interested in patch, anyway here it
is. All it needs now are "as" and := operators implemented correctly. I
plan to do that too, just as multiple interface inheritance (yes, it is
possible, the only problem is looking at the problem from the right
side. As long as you look at this thing as you described it, it is a no
go. If you turn around and open your eyes solution is as simple as
possible, the only problem is that you don't look at interface as you
should). If I plan correctly by the end of the weekend (it would be even
less if I would get some usable answers instead of "this doesn't work")
everything should work (I selected fpc (it has all I need, as I said I
don't mind little patches) for this job I'll be working on).
> Assigning/converting an interface to a class is impossible, which can
> be shown by this example.
>
> Var intf : IA; // has method C
> cl : SomeClass; // has method A,B
>
> begin
> intf:=someclass.create; // get reference to list with methods of
> interface
> cl:=intf; // assign list with methods of interface to
> // list of methods of class.
> cl.a; // cl has no knowledge about anything .c this
> // can't work.
> end;
>
> Even though at the point of "someclass.create" all info about the
class is
> available, only a list of offsets for methods in the interface is
passed.
> (so only method C at offset 0 in that table)
>
Yeah, heard that already, and the reason for that is that you don't
provide what is needed
> When assigning intf to cl, you assign that table back to the cl, the
full
> which needs a full VMT, with info about A and B. This makes the third
> statement
> (cl.a) impossible.
>
>
> _______________________________________________
> fpc-pascal maillist - fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
And the test source.
program project4;
{$mode objfpc}{$H+}{$MACRO+}
uses
Classes, SysUtils, libc
{ add your units here };
type
IA = interface
procedure A;
function Me: TInterfacedObject;
end;
IB = interface
procedure B;
end;
IC = interface(IA)
procedure C;
end;
ID = interface
procedure D;
end;
TD = class(TInterfacedObject)
end;
TC = class(TD, IA, IB, IC, ID)
constructor Create;
destructor Destroy; override;
// function Me: TInterfacedObject;
procedure A;
procedure B;
procedure C;
procedure D;
end;
constructor TC.Create;
begin
inherited Create;
A;
B;
C;
end;
destructor TC.Destroy;
begin
Writeln('TC.Destroy');
inherited Destroy;
end;
procedure TC.A;
begin
Writeln('a');
end;
procedure TC.B;
begin
Writeln('b');
end;
procedure TC.C;
begin
Writeln('c');
end;
procedure TC.D;
begin
Writeln('ddddddddddddddd');
end;
function Equals(const source: IUnknown): TObject;
begin
Result := source.Me;
end;
function SupportsInterface(aInterface: IUnknown; aIID: TGUID): boolean;
begin
Result := Supports(aInterface, aIID);
end;
function SupportsInterface(aClass: TClass; aIID: TGUID): boolean;
begin
Result := false;
if (aClass <> nil) then
if aClass.InheritsFrom(TInterfacedObject) then
Result := SupportsInterface(IUnknown(aClass), aIID);
end;
procedure testD(obj: ID);
begin
writeln('inside testD');
if obj <> nil then
obj.D
else
writeln('ua');
if SupportsInterface(obj, ID) then
writeln('yes')
else
writeln('ua');
end;
var
c: char;
AAAA: integer;
t: TC;
a: IA;
b: IB;
d: ID;
t2: TC;
cf: IUnknown;
cc: IC;
k: TInterfacedObject;
begin
Writeln(SizeOf(cf));
t := TC.Create;
a := t;
b := t;
AAAA := 500;
d := t;
cc := t;
a.A;
b.B;
writeln('t: ', integer(pointer(t)), ' --- a: ', integer(pointer(a)), '
--- b: ', integer(pointer(b)), ' --- d: ', integer(pointer(d)));
// here as should be treated same as :=
writeln('t: ', integer(pointer(t)), ' --- a: ', integer(pointer(t as
IA)), ' --- b: ', integer(pointer(t as IB)), ' --- d: ', integer(pointer
(t as ID)));
t2 := TC(Equals(a));
writeln('t2: ', integer(pointer(t2)));
t2 := TC(Equals(cc));
writeln('t2: ', integer(pointer(t2)));
d := nil;
d := t2; // if you look here I derived ID from IC, which is not
possible as you say
d.d;
a.A;
b.B;
// some junk testing code
if (t.InheritsFrom(TD)) then
Writeln('Inherits from TD')
else
Writeln('Does not Inherits from TD');
try
if SupportsInterface(t, IB) then
if SupportsInterface(cc, IA) then
if SupportsInterface(d, IB) then
writeln('yes')
else
writeln('nope');
except
writeln('nope, error');
end;
writeln('testD');
testD(ID(t));
a := nil;
b := nil;
cc := nil;
d := nil;
end.
----------------------------------------------------------------------
This mail sent through Horde-Toaster (http://qmailtoaster.clikka.com/)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: interfaces.patch
Type: text/x-patch
Size: 1246 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20050323/02dafecd/attachment.bin>
More information about the fpc-pascal
mailing list