[Erledigt] Interfaces und Instanzfreigabe

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
compmgmt
Beiträge: 351
Registriert: Mi 25. Nov 2015, 17:06
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4
CPU-Target: i386 + x86_64
Wohnort: in der Nähe von Stuttgart
Kontaktdaten:

[Erledigt] Interfaces und Instanzfreigabe

Beitrag von compmgmt »

Hallo zusammen,

Bisher habe ich noch nicht sonderlich viel mit Interfaces gemacht, eigentlich fast nur abstrakte Klassen, wenn ich eine gleichwertige Funktionalität benötigt habe.

Ich habe eine Instanz einer Klasse, welche von einem Interface erbt. Diese wird irgendwann mal erstellt und irgendwann freigegeben. Nun habe ich folgendes Problem: Folgendes funktioniert nicht:

Code: Alles auswählen

const
  STest = '{982DE917-23B3-4FEF-B427-54E82D7866D5}';
 
type
  ITest = interface(IUnknown)
    [STest]
    procedure Test; stdcall;
  end;
 
  TTest = class(TInterfacedObject, ITest)
    public
      procedure Test; stdcall; virtual;
  end;
 
...
 
procedure TTest.Test; stdcall;
begin
  WriteLn('Test method called');
end;
 
var
  C: TTest; // Class instance
  I: ITest; // Interface instance. Diese wird irgendwann mal vom Nutzer angefordert.
 
begin
  C := TTest.Create;
  if C.GetInterface(STest, I) then begin
    I.Test;
  end
  else WriteLn('Error');
  ReadLn;
  C.Free; // Hier krachts
  ReadLn;
end.

Der Zeitpunkt des erhalten des Interfaces ist in meinem Fall nicht direkt bestimmbar, ebenso wenig der Zeitpunkt des Freigebens, zumal ich das ganze später aus einer DLL exportieren möchte. Die Instanz kann allerdings schon vorher existieren und anschließend auch weiter verwendet werden. Testweise mache ich das aber erstmal ohne DLL.

Es kracht mit RunError 204, was laut https://www.freepascal.org/docs-html/user/userap4.html folgendes ist:
https://www.freepascal.org/docs-html/user/userap4.html hat geschrieben: 204 Invalid pointer operation
You will get this in several cases:
• if you call Dispose or Freemem with an invalid pointer
• ...


Wieso ist das so und was kann ich da machen?
Zuletzt geändert von compmgmt am Di 29. Jan 2019, 22:30, insgesamt 1-mal geändert.

Code: Alles auswählen

InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Interfaces und Instanzfreigabe

Beitrag von m.fuchs »

Füge folgendes in deinen Programm-/Unitkopf ein:

Code: Alles auswählen

{$INTERFACES Corba}  


Und schmeißt die Ableitung von IUnknown raus.

Andernfalls ist das Interface referenzgezählt und führt ein automagisches .Free durch.
Und danach bitte die Entwicklungsabteilung bei Borland dafür verfluchen, dass sie so einen Schwachsinn eingeführt haben.

BTW: Ich glaube die GUID kannst du dann auch weglassen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

compmgmt
Beiträge: 351
Registriert: Mi 25. Nov 2015, 17:06
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4
CPU-Target: i386 + x86_64
Wohnort: in der Nähe von Stuttgart
Kontaktdaten:

Re: Interfaces und Instanzfreigabe

Beitrag von compmgmt »

Danke, funktioniert. Die GUID benötige ich aber für C.GetInterface(). Außerdem wird diese (glaube ich) für die Identifikation benötigt, wenn ich das Interface über eine DLL bzw ein SharedObject exportiere.

Edit: IUnknown hat sich aber scheinbar Microsoft ausgedacht (https://docs.microsoft.com/en-us/windows/desktop/api/unknwn/nn-unknwn-iunknown) und die können wohl auch nicht schreiben. Anders kann ich mir jedenfalls nicht erklären wo das "o" in "Unknwn.h" ist.

Code: Alles auswählen

InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)

Antworten