Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Object (Interface) <> nil (https://www.delphipraxis.net/193802-object-interface-nil.html)

stahli 11. Sep 2017 15:56

AW: Object (Interface) <> nil
 
Zitat:

Zitat von EWeiss (Beitrag 1380805)
Ich möchte nichts anderes als meiner Anwendung mitteilen das dass erstellte Object Nil ist.

Um hier helfen zu können, müsste erst mal klar sein, wer das erstelle Objekt auf Nil setzt.
Das ist letztlich schon die falsche Beschreibung. Ein Objekt kann nicht auf Nil gesetzt werden. Dieses kann man höchstens freigeben (also dessen Speicherbereich wiederverwendbar machen).
Eine Variable kann man auf Nil setzen.

Willst Du also erkennen, ob das Objekt freigegeben wurde oder ob eine Variable auf Nil gesetzt wurde?

Eine diesbezügliche Interaktion zwischen DLL und Anwendung wird wohl in beiden Fällen nicht gehen (es sei denn, es würde ein Interface-Property als Informationsstelle benutzt).

Wenn die DLL außen vor bleiben kann und nur die Anwendung über die Objekt-Existenz informiert sein muss, gibt es mehrere (ziemlich triviale) Möglichkeiten.


Wenn Du die "Existenz Deines Objektes" nur in der Anwendung abfragen musst, die auch die Klasse (nicht nur das Interface kennt), und immer nur eine Instanz davon existieren kann, könntest Du eine Klassenvariable
Delphi-Quellcode:
PopupMenuExist: Boolean;
einrichten und diese im Constructor auf True und im Destructor auf False setzen.
Dann könntest Du abfragen, ob eine gütige Instanz existiert oder nicht.

Das setzt aber nicht Deine Variable auf Nil.
Dazu könntest Du evtl. eine globale Variable verwenden, die im Constuctor auf Self und im Destructor auf Nil gesetzt wird.

Oder Du folgst dem General und regelst die Rückinfo über ein Callback.


[EDIT]
Zusammenfassend die Frage: Wird aktuell der Destructor Deiner TPopupMenu-Klasse korrekt aufgerufen (egal unter welchen genauen Umständen)? Dann halte dort den Status für die Anwendung fest. Bestenfalls in einer globalen Variable gMyPopupMenu := Nil und im Contructor gMyPopupMenu := Self.
Dann kannst Du jederzeit auf Assigned(gMyPopupMenu) prüfen...
Das geht problemlos, wenn immer nur eine Instanz dieser Klasse leben kann.

EWeiss 11. Sep 2017 16:41

AW: Object (Interface) <> nil
 
Zu 1.
Es gibt keinen Destructor da hier jemand gesagt hat das ich das Interface nicht selbst auf NIL setzen kann.
Daher benötige ich den nicht.

Zu 2.
Ja im Contructor wird die Variable SkinPopUpMenu := self; zugewiesen.

Zitat:

Dann kannst Du jederzeit auf Assigned(gMyPopupMenu) prüfen...
Und genau das mache ich in der DLL um zu prüfen ob das Object (Interface wie auch immer) frei ist.

Damit habe ich aber der Anwendung immer noch nicht mitgeteilt das mein Object Nil ist.

Danke für eure Hilfe werde das wohl selbst regeln müssen.
Ohne Vollständigen Code nutzt euch das nichts da ihr nicht sehen könnt was abgeht.

gruss

Neutral General 11. Sep 2017 16:50

AW: Object (Interface) <> nil
 
Anwendung:
Delphi-Quellcode:
var popup: ISkinPopUpMenu;
begin
  popup := CTRL_PopUpMenuCreate(OnPopupDestroyed);
end;

procedure OnPopupDestroyed()
begin
  ShowMessage('Popup wurde in der DLL auf nil gesetzt!');
end;
DLL:
Delphi-Quellcode:
var
  CallbackZurAnwendung: TCallback;

function CTRL_PopUpMenuCreate(callback: TCallback): ISkinPopUpMenu; stdcall;
begin
  result := TSkinPopUpMenu.Create();
  CallbackZurAnwendung := callback;
end;

// ...
// Wenn das Popupmenu auf nil gesetzt wird:
CallbackZurAnwendung(PopupMenu);
PopupMenu := nil;

EWeiss 11. Sep 2017 16:56

AW: Object (Interface) <> nil
 
Danke werde es mal testen
Wenn dann ist das wohl die beste Lösung ohne zusätzliche Funktionen.

gruss

stahli 11. Sep 2017 17:28

AW: Object (Interface) <> nil
 
In jedem Fall würde ich den Destructor an Deiner Stelle überschreiben.
Du musst ja darin neben dem inherited nichts tun und Du musst ja Free auch nicht aufrufen, aber so kannst Du bei Bedarf mal einen Haltepunkt setzen und sehen, ob und wann Dein Objekt wirklich freigegeben wird (einfach nur zur Ablaufkontrolle).

Und Du solltest m.E. auch nicht davon sprechen, ob ein Objekt oder Interface = Nil ist, sondern ob eine Variable Nil ist.
Das ist auch zum eigenen Verständnis bei solchen Problemen wichtig, da es ja mehrere Variablen geben kann, die ein Objekt referenzieren.
Auch ändert die Objektfreigabe nichts an diesen Variablen. Lediglich Zugriffe auf diese können später unvorhersehbare Probleme bis hin zum Programmabsturz verursachen.

EWeiss 11. Sep 2017 17:54

AW: Object (Interface) <> nil
 
Zitat:

In jedem Fall würde ich den Destructor an Deiner Stelle überschreiben.
Du musst ja darin neben dem inherited nichts tun und Du musst ja Free auch nicht aufrufen, aber so kannst Du bei Bedarf mal einen Haltepunkt setzen und sehen, ob und wann Dein Objekt wirklich freigegeben wird (einfach nur zur Ablaufkontrolle).
leere funktion die nichts tut ?
Wenn du meinst das ist besser werde ich es addieren.

Zitat:

Und Du solltest m.E. auch nicht davon sprechen, ob ein Objekt oder Interface = Nil ist, sondern ob eine Variable Nil ist.
Verstehe ich nicht ganz einzelne Variablen ? Wenn doch das Interface aus mehreren besteht.

gruss

stahli 11. Sep 2017 18:31

AW: Object (Interface) <> nil
 
Im Destructor muss man natürlich inherited aufrufen.
Ich finde das übersichtlicher, diesen auch zu überschreiben wenn man Konstruktoren definiert (ist aber nur Gewohnheitssache).
Aber Du kannst halt einen Haltepunkt setzten und sehen, ob das Objekt überhaupt freigegeben wird und wann.


Zu den Objekten und Interfaces, schau mal, ob Dir das zum Verständnis hilft: http://www.delphipraxis.net/1288384-post13.html

Wenn Du auf ein Interface zugreifst, ist das letztlich der Zugriff auf ein Teilstück eines Objektes. Das ist also ein etwas eingeschränkter Zugriff auf die Daten und Methoden des Objektes.

Das hat aber mit Variablen direkt nichts zu tun.

Was ich sagen wollte ist, dass eine Freigabe eines Objektes keine Variable auf Nil setzt und eine Zuweisung von Nil an eine Variable kein Objekt (bzw. keinen Speicherplatz) freigibt. (Die einzige Ausnahme ist bei Verwendung der automatischen Referenzzählung und Zuweisung von Nil an die letzte referenzierende Variable. Die Referenzzählung bezieht sich dabei immer auf das Objekt hinter den Interfaces - also bei zwei Referenzen auf Interface A und 2 auf Interface B eines Objektes erhöht die Referenzzählung des Objektes auf 4. Es gibt nicht je zwei Referenzzählerwerte auf Interface A und B.)

Die Trennung von Objektfreigabe und Variablenreferenz = NIL muss man gerade bei so einer Problemlösungssuche trennen, weil man sich sonst sprachlich einfach nicht verstehen kann.
Delphi-Quellcode:
MyIntf := Nil;
kann zu einer Auflösung des Objektes führen oder auch nicht.
Auf eines von beiden zu reagieren sind zwei verschiedene Paar Schuhe.

EWeiss 11. Sep 2017 18:40

AW: Object (Interface) <> nil
 
Danke dir für die Infos..

gruss

EWeiss 11. Sep 2017 20:02

AW: Object (Interface) <> nil
 
Ich habe es jetzt so gemacht.

Anwendung:
Delphi-Quellcode:
type
  TPopUpState = (OnPopupDestroyed);
  POPUPSTATECALLBACK = procedure(PopUpState: TPopUpState); stdcall;
Delphi-Quellcode:
  PopUpMenu := CTRL_PopUpMenuCreate(PopUpCallback);
Delphi-Quellcode:
procedure PopUpCallback(PopUpState: TPopUpState); stdcall;
begin
  case PopUpState of
    OnPopupDestroyed:
      PopUpMenu := nil;
  end;
end;
DLL:
Delphi-Quellcode:
var
  PopUpCallback : POPUPSTATECALLBACK;
Delphi-Quellcode:
function CTRL_PopUpMenuCreate(callback: POPUPSTATECALLBACK): ISkinPopUpMenu; stdcall;
begin

  result := TSkinPopUpMenu.Create();
  PopUpCallback := callback;
end;
Wenn Nil..
Delphi-Quellcode:
if SkinPopUpMenu = nil then
  PopUpCallback(OnPopupDestroyed);
funktioniert ganz gut kann es so belassen.
Danke für die Hilfe.

gruss

stahli 11. Sep 2017 20:17

AW: Object (Interface) <> nil
 
Ok, fein.
Wenn es so klappt, ist es schön.
Ich will auch nicht nochmal zur Verwirrung beitragen, aber vielleicht kannst Du mal noch nach zwei Dingen schauen:

Hast Du Deine Klasse von TInterfacedPersistent abgeleitet oder von TInterfacedObject?
Wird Dein Destructor des Objektes irgendwann aufgerufen?

Ich vermute, dass Dein Objekt aktuell nicht freigegeben wird. Das wäre nicht unbedingt ein Drama, aber erzeugt dann halt ein Speicherleck.

Wenn Du Dich darum noch kümmern willst, könnte man dem noch nachgehen...


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:12 Uhr.
Seite 3 von 4     123 4      

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