Hallo Entwickler!<p>Ich benötige für eine Rotine eine Methode als Pointer. Es sollte dann ungefähr so aussehen:<p>Routine(@ObjMethode)<p>Ich weiß, daß man dies besser mit TObject gelöst hätte, aber leider ist die Routine nun mal so. Kann mir jemand helfen?<p>Gruss Andreas
Announcement
Collapse
No announcement yet.
Object Methoden als Pointer
Collapse
X
-
Hi
Könntest Du das mal genauer spezifizieren ? kleiner Code und warum Du es so brauchst ? Generell ist eine Object-Methode wie ein Event definiert, also ein Record ähnlich TMethod. D.h. es werden ZWEI Zeiger benötigt, einer auf den Code und einer als 1. Parameter Self auf das Object selber.
Gruß Hage
-
Hi,
Soweit ich weiß sind Objektmethodenzeiger keine echten Zeiger sondern
nur ein ein Offset von der VMT (Virtual Method Table) aus.
Wenn ich z.B. ein API-Callback aufrufe verwende ich eine nicht Objektmehtode und reiche den Aufruf eins zu eins an die Objektmethode weiter.
zB:
Type
TTest = class
public
procedure ObjMethod( x : TX );
end;
var
Test : TTest
procedure Method( x : TX );
implementation
procedure Method( x : TX );
begin
Test.ObjMethod(x);
end;
...
Es gibt bestimmt auch bessere Lösungen oder
Comment
-
Jo, in Deinem Beispiel gehst Du über eine globale Object Instance variable um dann eine Methode aufzurufen. Das kann fehlerträchtig sein.
Eine Object-Methode, oder kurz Methode, ist ein record
<pre>
type
TMethod = packed record
Data: Pointer;
Code: Pointer;
end;
</pre>
Auch als Event benutzt.
Um eine Object Methode aufzurufen muß man deren Typ, (static, virtual, dynamic) und dessen Aufrufkonvention unterscheiden (pascal, register, stdcall, cdecl, safecall).<br>
Eine als static deklarierte Methode wird durch den Compiler zur Compilerungszeit aufgelösst, d.h. der Compiler erzeugt direkt einen CALL zur entsprechenden Codeadresse, hardcoded.
<pre>
Self.Free // static Object Methode <br>
mov eax,self
call $xxxxxxxxx // Aufruf der static Object Methode<br>
<br>
Self.InstanceSize // static class Methode<br>
mov eax,[eax] // eax = Self.ClassType = type TClass
call $xxxxxxxxx // Aufruf einer static class Methode<br>
<br>
Self.Destroy // virtual object method<br>
mov eax,self
mov ecx,[eax] // eax = Self.ClassType = type TClass
call dword ptr [ecx + vmtDestroy] // aufruf indirekt über die VMT<br>
<br>
Self.CallDynMethod(12) // Aufruf einer dynm. methode<br>
mov eax,self
mov edx,12 // Index in DMT
call GetDynaMethod // ermittle dynm. Methode
mov eax,self
call ecx
</pre>
Fazit, virtuelle Object Methoden werden NICHT über deren VMT Slot aufgerufen, diese dynamische Aufrufkonvention wird nur in dynamischen methoden benutzt, also alle mit dynamic oder message definierten Methoden. Virtuelle Methoden nutzen dagegen indirekte calls über die VMT=virtuelle Methoden Table.
Deren Auflösung=Indizierung durch den VMT-Slot Offset wird während der Compilierungszeit hardcoded.
Gruß Hage
Comment
Comment