Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   pointer auf Interface als messageparameter (https://www.delphipraxis.net/159423-pointer-auf-interface-als-messageparameter.html)

snook 27. Mär 2011 14:56

Delphi-Version: 5

pointer auf Interface als messageparameter
 
hallo,

ist es möglich einen pointer auf ein interface irgendwie in einen messageparameter zu packen?
folgendes konstrukt funktioniert zwar beim umwandeln pinterface --> pointer, aber zurück gibts ne AV

Delphi-Quellcode:
type
  IPlugIn = interface(IUnknown)
    ...
  end;

  TCustomPlugIn = class(TInterfacedObject, IPlugIn)
    ...
  end;

  PPlugIn = ^IPlugIn

  PPlugInEvent = ^TPlugInEvent;
  TPlugInEvent = packed record
    ...
    PlugInAddr: LongInt;
  end;


function AsPPlugIn(const PlugIn: IPlugin): Pointer;
begin
  GetMem(result,SizeOf(PPlugIn));
  PPlugIn(result) := @PlugIn;
end;

function AddEvent(...const PlugIn: IPlugIn): integer;
begin
  ...
  PPlugInEvent(FEventList[result])^.PlugInAddr := LongInt(AsPPlugIn(PlugIn));
// liefert beim Auswerten für PPlugIn(PlugInAddr)^: (TCustomPlugin($Adresse) as IPlugIn)
end;

// bei einem späteren Aufruf gibts aber ne AV:

procedure HoleInterfaceAusEvent(index: integer; out PlugIn);
begin
  PlugIn := PPlugIn(PPlugInEvent(FEventList[index])^.PlugInAddr)^;
// hier sieht man bei Ausdruck überwachen nur noch PPlugIn(PPlugInEvent(FEventList[index])^.PlugInAddr)^ = (Pointer($Adresse) as IPlugIn)
end;
gibt es da irgendeine andere möglichkeit an das interface zu kommen?

himitsu 27. Mär 2011 15:17

AW: pointer auf Interface als messageparameter
 
Wozu willst du das in einen Pointer casten?

Nimm doch einfach das Interface als Resulttyp.

PS: Wenn du wild mit Pointern castest, dann kann es leicht mal passieren, daß due die Referenzzählung "beschädigst".


Ein Interface ist ja quasi schon intern ein Zeiger, nur eben mit einer ordentlichen Referenzbehandlung.

snook 27. Mär 2011 15:25

AW: pointer auf Interface als messageparameter
 
ja das problem ist, dass ich das interface als msg.wparam (msg: TMessage) übergeben möchte, und zwar ohne dabei die referenzzählung zu erhöhen. und irgendwie habe ich das gefühl, dass ein interface nciht nur ein zeiger ist, sondern da auch noch infos über das eigentlich objekt drinnenstehen. ich glaube mal gelesen zu haben, dass ein interface aus dem methodentable des interfaces und nem zugehörigen offset, je nachdem wer das interface gerade implementiert besteht. kann es sein, dass mir deswegen beim speichern der interfacevariable a la pointer := @interface die infos über den offset verloren gehen?

edit:

im prinzp soll derjenige der die message bekommt das ganze dann so auswerten können:

Delphi-Quellcode:
var Sender: IPlugIn;
begin
  Sender := PPlugIn(msg.WParam)^;
end;
soweit ich das verstanden habe, ist ja dann die refernzzählung sowieso ausgehebelt, weil ich das interface als pointer übergebe und delphi da dann nciht mitzählt. ich will halt nur nciht den empfänger der message dafür verantwortlich machen das interface wieder auf nil zu setzen, bis auf das was er selber zuordnet

Namenloser 27. Mär 2011 15:30

AW: pointer auf Interface als messageparameter
 
Kann es sein, dass du den Pointer auf eine lokale Interface-Variable übergibst? Das Interface wird nämlich beim Verlassen der Funktion automatisch zerstört, der Pointer zeigt dann ins nirgendwo.

snook 27. Mär 2011 15:42

AW: pointer auf Interface als messageparameter
 
hmmm ich übergeben ihn an das ergebnis der funktion AsPPlugIn...

ahhh mir fällt da was ein, ich übergebe das interface als const-parameter an die funktion AsPPlugIn
liegt es daran, dass diese referenz dann nach verlassen der funktion AsPPlugIn wieder gelöscht wird?

snook 27. Mär 2011 16:00

AW: pointer auf Interface als messageparameter
 
perfekt das wars!
eine frage zum verständnis hab ich noch. ist es möglich, den speicherbereich, auf den eine interfacevariable zeigt, mit move zu kopieren? damit ließe sich das ganze dann doch wieder in funktion packen oder irre ich mich?

so nach dem motto:

Delphi-Quellcode:
function StoreInterfaceToPointer(const AInt: IInterface): Pointer
begin
  new(result, SizeOf(AInt));
  move(AInt, result, SizeOf(AInt));
end;
wobei das jetzt nciht funktioniert

Namenloser 27. Mär 2011 16:05

AW: pointer auf Interface als messageparameter
 
Vereinfacht gesagt sieht die Speicherstruktur so aus:
Code:
(@ Steht für einen Pointer)

Stack————————————————>| Heap—————————————————————————————————————————————————————————————————————>
Variable:                                            
• @ Interface ————————>Interface:
                       • @ Objekt —————————————————>Objekt:
                       • @ Interface-Methode 1      • @ VMT ———————————> Methodentabelle:
                       • @ Interface-Methode 2      • Felder und Co.    • @ Objekt-Methode 1
                       • @ Interface-Methode n                          • @ Objekt-Methode 2
                                                                        • @ Objekt-Methode n
@Variable = Pointer auf die Variable auf dem Stack
Pointer(Variable) = Pointer auf Interface auf dem Heap

Ersteres ist eine schlechte Idee, da natürlich der Stack sich jederzeit ändert kann.
Zweiteres ist auch eine schlechte Idee, da am Ende einer Funktion Delphi automatisch alle lokalen Interfaces freigibt, d.h. es wird erst Variable._Release aufgerufen, wenn der Refcounter 0 ergibt, wird das Objekt freigegeben.
Anschließend wird aber IMMER das Interface selbst freigegeben, auch wenn das Objekt nicht zerstört wird.

Wenn du also einen Pointer auf ein lokales Interface woanders weiter verwendest, geht das höchstwahrscheinlich in die Hose.

snook 27. Mär 2011 16:12

AW: pointer auf Interface als messageparameter
 
wow dankeschön. jetzt hab ich mal ein "bild" davon wie interfaces angelegt sind. :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:20 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