AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Interfaces: Ich werd' irre!

Ein Thema von Fingolfin · begonnen am 8. Jun 2004 · letzter Beitrag vom 11. Jul 2004
Antwort Antwort
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#1

Interfaces: Ich werd' irre!

  Alt 8. Jun 2004, 21:28
Hallöle, ich möchte per Interfaces ermöglichen, daß verschiedene Units an ein Objekt rankommen ohne es instantiieren zu müssen (quasi ein Singleton, der von überall nur duch Einbindung der Unit zugreifbar sein soll).

Ich habe es folgendermaßen versucht:

Code:
interface

type

  ITest = interface
  ['{74B2F6FC-1464-43E2-A5FB-74A889F723F2}']
    procedure Show;
  end;

  function Test: ITest;

implementation

uses
  Dialogs, SysUtils;

type

  TTest = class(TInterfacedObject, ITest)
  private
  public
    procedure Show;
  end;

var
  FTest: TTest;

function Test: ITest;
begin
  if not Assigned(FTest) then
    FTest := TTest.Create;
    Result := FTest as ITest;
end;

{TTest}

destructor TTest.Destroy;
begin
  inherited;
end;

procedure TTest.Show;
begin
  ShowMessage('');
end;

initialization
  FTest := nil;
finalization
  if Assigned(FTest) then
    FTest.Free;
Das Aufrufen von Test.Show im Hauptprogramm funktioniert auch erstmal gut. Wenn ich die Prozedur allerdings ein zweites Mal ausführe, crasht er mir weg, da vorher anscheinend schon alle Referenzen auf das Interface verschwinden (direkt nach dem ersten Aufruf von Test.Show). Anscheinend besteht das Objekt FTest aber trotzdem noch, da ich per Debugger den RefCount sehen kann.



Also wird anscheinend nach jedem Zugriff eine Funktion das Objekt FTest freigegeben, was ich eigentlich auch nicht möchte, da die Daten ja eine ganze Weile bereitstehen sollen.

Für Anmerkungen und Hilfe wäre ich sehr dankbar. Bitte bringt ein wenig Licht in mein Dunkel.

Bitte Bitte.

Fingolfin
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Interfaces: Ich werd' irre!

  Alt 8. Jun 2004, 22:04
Ich glaube Du bist auf den einzigen Fehler gestoßen, den Delphi bei Interfaces in Bezug auf die Automatische Referenzzählung besitzt.

Das Problem ist, das Du dir einen Zeiger auf das Objekt merkst, jedoch als Rückgabewert der Funktion einen Interfacezeiger lieferst. Wird der zurückgegebene Interface-Zeiger nicht mehr benötigt, geht der Ref-Counter auf 0 zurück und das Objekt wird freigegeben. Jedoch merkst Du dir den zeiger auf das (nicht mehr vorhandene) Objekt. Und das wird nicht zurückgesetzt.

Lösung 1: Nimm als Modulvariable ein ITest statt einem TTest
Delphi-Quellcode:
var
  FTest: ITest;
Lösung 2: Zurücksetzen der Modulvariable im Destruktur
Delphi-Quellcode:
destructor TTest.Destroy;
begin
  FTest := nil;
  inherited;
end;
Lösung nicht getestet, jedoch aufgrund eigener Erfahrungen müsste das dein Problem lösen.
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#3

Re: Interfaces: Ich werd' irre!

  Alt 8. Jun 2004, 22:11


Oha, VIELEN DANK! Jetzt wird mir einiges klar. Und noch besser: Es funktioniert auch noch einwandfrei.
Interfaces fielen mir schon immer schwer, aber so langsam lüftet sich der Schleier.



Das geht aber echt schnell hier mit hilfreichen Antworten.

Fingolfin
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#4

Re: Interfaces: Ich werd' irre!

  Alt 10. Jul 2004, 20:07
Hallo nochmal. Anscheinend begehe ich immer noch einen ähnlichen Folgefehler.

Ich benutze ITest zur Datenhaltung. Das Interface und dementsprechend auch TTest beinhaltet mehere Collections, die zum Teil selbst Interfaces haben. Die Referenzzählung ist meiner Meinung nach korrekt implementiert, aber in dem Moment, in dem ich Getinterface nutzen möchte, wird der Referenzzähler des jerweiligen Objekt um 1 erhöht und dann wieder gesenkt, was den Aufruf des Destruktors nach sich zieht.

Ich möchte eigentlich ein Verhalten, bei dem ich gefahrlos auf ein Interface prüfen kann ohne mit gleich das Objekt zu zerschießen.

Vielleicht hast du (oder andere) ja eine Idee, was ich falsch mache.



Vielen Dank im Voraus,

Fingolfin
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#5

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 15:01
Im Nachhinein glaube ich, mich etwas zu kompliziert ausgedrückt zu habe. Ich versuche es nochmal einfacher:

Hier mein Interface und die Klasse, die es einbindet:

Code:
  ITest = interface
  ['{93942268-B484-4BBD-A907-CA8B8B5208BF}']
  end;

  TTest = class(TInterfacedObject, ITest)
  end;
Dann erstelle ich mein Objekt:

Code:
var
  test: TTest;
begin
  test := TTest.Create;
end;
Und jetzt möchte ich per GetInterface wissen, ob mein Objekt das ITest interface implementiert:

Code:
var
  testint: ITest;
begin
 if test.GetInterface(itest, testint) then
  begin
    //hier geht schon nix mehr, weil test freigegeben wurde
  end;
end;


Das ist doch ein Grundlagen-Problem oder? Irgendwie fehlt mir der Durchblick.

Hilfe

Danke im Voraus,

Fingolfin
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#6

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 18:07
GetInterface - Kenn ich nicht?

Aber dein Problem ist evtl. genau des Bug der Referenzzählung, wenn mit Objekt und Interfacezeigern gemisch operiert wird.
Probier aber einfach mal folgendes (ohne Garantie/test):
Delphi-Quellcode:
if test is ITest then
  (test as ITest).InterfaceMethode
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#7

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 20:22
Danke für deinen Kommentar.

Code:
(test as ITest).InterfaceMethode
funktioniert ohne Probleme.

Die Abfrage:

Code:
if test is ITest then
führt aber leider zu einem "Operator not applicable to this operand type" Fehler.

@GetInterface
Ich war der Meinung, daß das Casten bei Interfaces nur per GetInterface möglich ist. Ohne das is also die Abfrage bringt mir das as leider nichts.



Fingolfin
  Mit Zitat antworten Zitat
Benutzerbild von mirage228
mirage228

Registriert seit: 23. Mär 2003
Ort: Münster
3.750 Beiträge
 
Delphi 2010 Professional
 
#8

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 20:25
Zitat von Fingolfin:
Die Abfrage:

Code:
if test is ITest then
führt aber leider zu einem "Operator not applicable to this operand type" Fehler.


Fingolfin
Hi,

dazu könntest du dir die Methode Hier im Forum suchenQueryInterface in der OH anschauen.

mfG
mirage228
David F.

May the source be with you, stranger.
PHP Inspection Unit (Delphi-Unit zum Analysieren von PHP Code)
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#9

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 20:45
Hallo mirage. Mit

Code:
  if QueryInterface(ITest, t) = S_OK then
  begin
    t.InterfaceMethode;
  end;
funktioniert es.

Allerdings steht in der OH ja, daß man gerade QueryInterface vermeiden und GetInterface nutzen soll. GetInterface macht eigentlich auch nur Folgendes:

Code:
  if GetInterface(IID, Obj) then
    Result := S_OK
  else
    Result := E_NOINTERFACE;
Was an der QueryInterface-Variante dann auch noch komisch ist, ist die Tatsache, daß ein danach ausgeführtes

Code:
  t := nil;
anscheinden nix bewirkt.

Jetzt bin ich echt verwirrt, soll ich jetzt direkt QueryInterface nehmen weil's funktioniert, obwohl die OH es nicht gut findet? Ich habe da etwas Angst, daß mir das später noch irgendwelche Probleme bereitet.

Danke im Voraus,

Fingolfin
  Mit Zitat antworten Zitat
Fingolfin

Registriert seit: 8. Okt 2003
62 Beiträge
 
#10

Re: Interfaces: Ich werd' irre!

  Alt 11. Jul 2004, 20:58
Oha, habe natürlich Unsinn erzählt.

Anstatt:

Code:
  if QueryInterface(ITest, t) = S_OK then
  begin
    t.InterfaceMethode;
  end;
muß es natürlich:

Code:
  if test.QueryInterface(ITest, t) = S_OK then
  begin
    t.InterfaceMethode;
  end;
heißen. Und das funktioniert genausowenig wie QueryInterface.



Fingolfin
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:17 Uhr.
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