Prechádzať zdrojové kódy

* improved getinterfaceentry and getinterfaceentrybystr
* fixed InitInterfacePointers (just etStandard interface pointers need to be initialized!)
* to fix: EntryOffset and IOffset should be merged (compiler thing)
* to fix: Interface pointer allocation in TClass for not etStandard interfaces is not necessary! (also compiler thing)

git-svn-id: trunk@5559 -

ivost 18 rokov pred
rodič
commit
73713d14e3
1 zmenil súbory, kde vykonal 36 pridanie a 32 odobranie
  1. 36 32
      rtl/inc/objpas.inc

+ 36 - 32
rtl/inc/objpas.inc

@@ -135,17 +135,26 @@
       procedure InitInterfacePointers(objclass: tclass;instance : pointer);
       procedure InitInterfacePointers(objclass: tclass;instance : pointer);
 
 
         var
         var
-           intftable : pinterfacetable;
-           i : longint;
+          i: integer;
+          intftable: pinterfacetable;
+          Res: pinterfaceentry;
         begin
         begin
           while assigned(objclass) do
           while assigned(objclass) do
             begin
             begin
-               intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
-               if assigned(intftable) then
-                 for i:=0 to intftable^.EntryCount-1 do
-                   ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
-                     pointer(intftable^.Entries[i].VTable);
-               objclass:=pclass(pointer(objclass)+vmtParent)^;
+              intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
+              if assigned(intftable) then
+              begin
+                i:=intftable^.EntryCount;
+                Res:=@intftable^.Entries[0];
+                while i>0 do begin
+                   if Res^.EntryType = etStandard then
+                     ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
+                       pointer(Res^.VTable);
+                  inc(Res);
+                  dec(i);
+                end;
+              end;
+              objclass:=pclass(pointer(objclass)+vmtParent)^;
             end;
             end;
         end;
         end;
 
 
@@ -564,39 +573,37 @@
             (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
             (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
         end;
         end;
 
 
-      function TObject.getinterface(const iid : tguid;out obj) : boolean;
+      function getinterfacebyentry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
         var
         var
-          IEntry: pinterfaceentry;
           Getter: function: IInterface of object;
           Getter: function: IInterface of object;
         begin
         begin
           Pointer(Obj) := nil;
           Pointer(Obj) := nil;
-          IEntry:=getinterfaceentry(iid);
           if Assigned(IEntry) then
           if Assigned(IEntry) then
           begin
           begin
             case IEntry^.EntryType of
             case IEntry^.EntryType of
               etStandard:
               etStandard:
                 begin
                 begin
-//                  writeln('Doing etStandard cast of ', classname(), ' with self = ', ptrint(self), ' and offset = ', IEntry^.IOffset);
-                  Pointer(Obj) := Pointer(PtrInt(self) + IEntry^.IOffset);
+                  writeln('Doing etStandard cast of ', TObject(Instance).classname(), ' with self = ', ptruint(Instance), ' and offset = ', IEntry^.IOffset);
+                  Pointer(Obj) := Pointer(PtrInt(Instance) + IEntry^.IOffset);
                 end;
                 end;
               etFieldValue:
               etFieldValue:
                 begin
                 begin
-//                  writeln('Doing etFieldValue cast of ', classname(), ' with offset = ', IEntry^.EntryOffset);
-                  Pointer(obj) := ppointer(Pointer(Self)+IEntry^.EntryOffset)^;
+                  writeln('Doing etFieldValue cast of ', TObject(Instance).classname(), ' with offset = ', IEntry^.EntryOffset);
+                  Pointer(obj) := ppointer(Pointer(Instance)+IEntry^.EntryOffset)^;
                 end;
                 end;
               etVirtualMethodResult:
               etVirtualMethodResult:
                 begin
                 begin
-//                  writeln('Doing etVirtualMethodResult cast of ', classname());
-                  TMethod(Getter).data := self;
-                  TMethod(Getter).code := ppointer(ptrint(self) + IEntry^.EntryOffset)^;
-                  Pointer(obj) := Getter();
+                  writeln('Doing etVirtualMethodResult cast of ', TObject(Instance).classname());
+                  TMethod(Getter).data := Instance;
+                  TMethod(Getter).code := ppointer(ptrint(Instance) + IEntry^.EntryOffset)^;
+                  Pointer(obj) := Pointer(Getter());
                 end;
                 end;
               etStaticMethodResult:
               etStaticMethodResult:
                 begin
                 begin
-//                  writeln('Doing etStaticMethodResult cast of ', classname());
-                  TMethod(Getter).data := self;
+                  writeln('Doing etStaticMethodResult cast of ', TObject(Instance).classname());
+                  TMethod(Getter).data := Instance;
                   TMethod(Getter).code := pointer(IEntry^.EntryOffset);
                   TMethod(Getter).code := pointer(IEntry^.EntryOffset);
-                  Pointer(obj) := Getter();
+                  Pointer(obj) := Pointer(Getter());
                 end;
                 end;
             end;
             end;
           end;
           end;
@@ -605,17 +612,14 @@
             IInterface(obj)._AddRef;
             IInterface(obj)._AddRef;
         end;
         end;
 
 
+      function TObject.getinterface(const iid : tguid;out obj) : boolean;
+        begin
+          Result := getinterfacebyentry(self, getinterfaceentry(iid), obj);
+        end;
+
       function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
       function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
-        var
-          IEntry: pinterfaceentry;
         begin
         begin
-          IEntry:=getinterfaceentrybystr(iidstr);
-          if not Assigned(IEntry) then
-          begin
-            Pointer(obj) := nil;
-            result := false;
-          end else
-            result := getinterface(IEntry^.IID^, obj);
+          Result := getinterfacebyentry(self, getinterfaceentrybystr(iidstr), obj);
         end;
         end;
 
 
       class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
       class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
@@ -648,7 +652,7 @@
           Res: pinterfaceentry;
           Res: pinterfaceentry;
         begin
         begin
           getinterfaceentrybystr:=nil;
           getinterfaceentrybystr:=nil;
-          intftable:=getinterfacetable;
+          intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
           if assigned(intftable) then begin
           if assigned(intftable) then begin
             i:=intftable^.EntryCount;
             i:=intftable^.EntryCount;
             Res:=@intftable^.Entries[0];
             Res:=@intftable^.Entries[0];