Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wie erstelle ich einen Zeiger auf die Klasseninstanz (https://www.delphipraxis.net/157479-wie-erstelle-ich-einen-zeiger-auf-die-klasseninstanz.html)

FriendOfDelphi 13. Jan 2011 10:02

Delphi-Version: 5

Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Hallo Wissende,

wie kann ich beim Aufruf einer Methode/Prozedur innerhalb eines Objektes den Zeiger der aktuellen Klasseninstanz als Parameter mitgeben?

Also ungefähr so:
"MeineProzedur(Zeiger auf die Klasse);"

Ich habe es folgendermaßen probiert:
Delphi-Quellcode:
MeineProzedur(self);
Aber so funktioniert es nicht.

Deep-Sea 13. Jan 2011 10:06

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Wieso genau funktioniert es denn nicht?
Und: Willst du nun die Instanz oder die Klasse übergeben?

himitsu 13. Jan 2011 10:08

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Wieso soll das nicht funktionieren?

Eine Objektreferenz ist doch auch "nur" ein Zeiger.

QuickAndDirty 13. Jan 2011 10:08

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
innerhalb von
Object Methoden referenziert sich jedes Objekt über self !
Wenn du von einer Prozedur aus, aus dem Hauptprogramm heraus (dpr Datei) oder aus einer Methode heraus ein anderes Object referenzieren willst musst du schon den Variablen Namen angeben.

Es kann auch mal vorkommen das self = nil ist...oder noch schlimmer das das Object sich selbst zerstört hat (kann bei formularen passieren) aber du immer noch in einer der Methoden des bereits zerstörten Objektes bist...dann verweißt self nirgendwo hin wo es soll...

Bbommel 13. Jan 2011 10:12

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Mein erster Gedanke war auch: Doch, genau so funktioniert es. :) Zeig uns doch mal etwas mehr Code und die Fehlermeldung.

himitsu 13. Jan 2011 10:12

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Achso, jetzt hab ich dich auch verstanden. (nach QAD)

Jupp, Self ist ein "versteckter" Parameter, welcher an jede Methode mit übergeben wird und darin steht die Referenz zu dem Objekt, in welchem die Methode grade ausgeführt wird.

Warum steht sowas eigentlich in der OH?
Delphi-Referenz durchsuchenSelf Delphi-Referenz durchsuchenTObject.Self

FriendOfDelphi 13. Jan 2011 10:29

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Ok, ich sollte wohl lieber das ganze Problem schildern:

Ich verwende ein Library von der ich nur eine DCU-Datei habe (liefert der Hardware-Hersteller mit).
Aus dieser Library verwende ich eine Methode, der ich die Adresse einer Prozedur (Callback-Routine) übergebe, die aufgerufen wird, wenn sich in der Hardware etwas tut. Diese kann leider nicht Teil meiner Klasse sein, da nur ein normaler Prozedurzeiger übergeben werden darf (4 Byte).

Weiterhin besteht die Möglichkeit der Library-Methode einen beliebigen Parameter/beliebigen Zeiger vom Typ Cardinal zu übergeben.
Hier will ich den Zeiger der Klasseninstanz übergeben.

Diesen Zeiger bekommt man dann beim Aufruf der Callback-Routine über den zuvor übergebenen Parameter (Variable) wieder zurück.
Diesen Zeiger möchte ich dann auf den Pointer der Klassenistanz "zurück-casten" und dann eine public-Methode meiner Klasse über diesen Zeiger aufrufen.

Deep-Sea 13. Jan 2011 10:36

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Zitat:

Zitat von FriendOfDelphi (Beitrag 1074410)
Diese kann leider nicht Teil meiner Klasse sein, da nur ein normaler Prozedurzeiger übergeben werden darf (4 Byte).

Kann schon, wenn es eine Klassenmethode ist.

Aber wo ist jetzt das Problem?

FriendOfDelphi 13. Jan 2011 11:23

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Zitat:

Zitat von Bbommel (Beitrag 1074407)
Mein erster Gedanke war auch: Doch, genau so funktioniert es. :) Zeig uns doch mal etwas mehr Code und die Fehlermeldung.

Delphi-Quellcode:
[...schnipp...]

Procedure Callback(pAddr:PAmsAddr; pNotification:PAdsNotificationHeader; hUser:Longword); stdcall;
begin
  //mache irgendwas
  //beim Aufruf der Prozedur soll in hUser der Zeiger der Klasseninstanz stehen
end;

[...schnipp...]
Das ist die Methode, die ich aus der Library aufrufe:
Delphi-Quellcode:
[...schnipp...]

result := AdsSyncAddDeviceNotificationReq( @serverAddr, ADSIGRP_DEVICE_DATA,
                                           ADSIOFFS_DEVDATA_ADSSTATE,
                                           @adsNotificationAttrib,
                                           @Callback, //hier steht die Adresse der Callback-Routine
                                           Longword(@???), //an dieser Stelle will ich den Zeiger der Klasseninstanz übergeben
                                           @hDevNotification );
[...schnipp...]
Hier steht das Beispiel, an dem ich mich orientiert habe: http://infosys.beckhoff.com/index.ph...4.htm&id=10260

Deep-Sea 13. Jan 2011 11:33

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Beim Aufruf:
Delphi-Quellcode:
DieFunktion(Longword(Self));


Beim Callback:
Delphi-Quellcode:
var
  LInstanz: TMeinObjekt;
begin
  LInstanz := TMeinObjekt(hUser);
end;

Thom 13. Jan 2011 11:52

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Delphi-Quellcode:
type
  TMyClass = class(...)
  public
    procedure CallbackProc(pAddr: PAmsAddr; pNotification: PAdsNotificationHeader);
    procedure InitCallback;
  end;

procedure Callback(pAddr: PAmsAddr; pNotification: PAdsNotificationHeader; hUser: Longword); stdcall;
begin
  TMyClass(hUser).CallbackProc(pAddr,pNotification);
end;

procedure TMyClass.CallbackProc(pAddr: PAmsAddr; pNotification: PAdsNotificationHeader);
begin
end;

procedure TMyClass.InitCallback;
var
  Result: ...;
begin
  Result:=AdsSyncAddDeviceNotificationReq(@serverAddr,ADSIGRP_DEVICE_DATA,
                                          ADSIOFFS_DEVDATA_ADSSTATE,
                                          @adsNotificationAttrib,
                                          @Callback, //hier steht die Adresse der Callback-Routine
                                          Longword(self), //an dieser Stelle will ich den Zeiger der Klasseninstanz übergeben
                                          @hDevNotification);
end;
P.S.: Da war Deep-Sea schneller - aber auch kürzer... :wink:

himitsu 13. Jan 2011 11:52

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Man könnte zwar auch eine externe Prozedur nehmen, aber so isses bestimmt schöner aufgeräumt.

PS: Das "static" nicht vergessen.
Delphi-Quellcode:
type
  TMeinObjekt = class(...)
    class procedure Callback(Addr: PAmsAddr; Notification: PAdsNotificationHeader; User: LongWord); stdcall; static;
    procedure InnerCallback(Addr: PAmsAddr; Notification: PAdsNotificationHeader);
  end;

procedure TMeinObjekt.Callback(Addr: PAmsAddr;
  Notification: PAdsNotificationHeader; User:Longword);
begin
  TMeinObjekt(hUser).InnerCallback(Addr, Notification);
end;

var MeinObjekt: TMeinObjekt;

AdsSyncAddDeviceNotificationReq(..., @MeinObjekt.Callback, LongWord(MeinObjekt), ...);
[edit]
da war ja nochwer fast genauso schnell :lol:

FriendOfDelphi 13. Jan 2011 12:45

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Ich bin ja begeistert, was ihr da so hinzaubert... :o

Aber könnt ihr mir mal erklären, warum ihr das so macht?

Bitte :?

himitsu 13. Jan 2011 12:58

AW: Wie erstelle ich einen Zeiger auf die Klasseninstanz
 
Wir übergeben als User-Parameter die Objektinstanz und als Zeiger eine Prozedur, statische Klassenmethode (welche quasi auch nur eine Prozedur darstellt)

Davor haben wir uns eine Prozedur gebastelt, deren Signazur derer entspricht, welchge von als Callback verlangt wird
und darin wird dann einfach nur über den übergebenen Methodenzeiger auf eine Methode dieses Objektes zugeriffen/umgeleitet.

Als Ergebnis wird somit also eine Methode eines Objekts aufgerufen.



PS: Ein "Zeiger" auf eine Methode enthält intern auch zwei Zeiger > einmal auf das Objekt und dann noch auf die Methode.
"Zeiger" ... ach, schau dir einfach mal an, was die .OnIrgendwas Events deiner VCL haben, also nahezu alles was du im IO deinen VCL-Komponenten als Ereignisse zuweisen kannst, bzw. der Typ der zugehörigen Event-Property.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz