Island-Windows COM, when the Compiler magic kicks in for memory management?

I tried to wrap up the Win32 COM connection point interface, and I have the following code.

My question is: in order for Island COM memory management to kick in, do I HAVE TO DO the deference
var lCP: IConnectionPoint := lpCP^;

var lCPC: IConnectionPointContainer := lpCPC^;

Or it is totally unnecessary, while I can use the interface pointer (lpCP^, and lcCPC^) directly?

method InterfaceConnect(const aSource: IUnknown; const aIID_ConnectionPoint: ^GUID; const aSink: IUnknown; aConnection: ^DWORD);
begin
  var lpCPC: ^IConnectionPointContainer;
  var lpCP: ^IConnectionPoint;
  var IID_ConnectionPointContainer: GUID;

  IID_ConnectionPointContainer := guidOf(IConnectionPointContainer);
  aConnection^ := 0;

  if Succeeded(aSource.QueryInterface(@IID_ConnectionPointContainer, (^^Void)(@lpCPC))) then begin
    var lCPC: IConnectionPointContainer := lpCPC^; // is this necessary for COM gc to kick in??
    if Succeeded(lCPC.FindConnectionPoint(aIID_ConnectionPoint, (^IConnectionPoint)(@lpCP))) then begin
      var lCP: IConnectionPoint := lpCP^; // is this necessary for COM gc to kick in?
      lCP.Advise(aSink, aConnection);
    end;
  end;
end;

Island com memory management works on com interfaces only, not on pointers to them no. Why are you using pointers above at all though?

  var lpCP: IConnectionPoint;  
  if Succeeded(aSource.QueryInterface(@IID_ConnectionPointContainer, (^^Void)(@lpCPC))) then begin
     // Should be fine here already.

@ck
I have to use pointer as that is required by the COM APIs - they are in charge of allocating memory. If I don’t use pointers, what else can I do?

What I mean is, QueryInterface takes a pointer to an interface and puts the interface in there. It shouldn’t need an extra level of indirection (IUnknown already IS a pointer after all).

1 Like

Thank you for the heads up.

Now I see I got confused myself with C++ practice.

  • In C++, any variable of IUnknown type is a value-type struct, therefore they are passed into QueryIntetface as void** (i.e., IUnknown** cast as un-typed)

However, in Island (or Delphi), any variable of IUnknown type is a reference-type which itself is just a pointer. Hence no need (actually, wrong, and won’t work) to pass as an extra level of pointer to QueryInterface.

Thanks again. And the correct code should be:

method InterfaceConnect(const aSource: IUnknown; var IID: GUID; const aSink: IUnknown; aConnection: ^DWORD);
begin
  var IID_ConnectionPointContainer: GUID := guidOf(IConnectionPointContainer);
  var lCPC: IConnectionPointContainer;
  var lCP: IConnectionPoint;

  aConnection^ := 0;

  if Succeeded(aSource.QueryInterface(@IID_ConnectionPointContainer, (^LPVOID)(@lCPC))) then
    if Succeeded(lCPC.FindConnectionPoint(@IID, @lCP)) then 
       lCP.Advise(aSink, aConnection);
end;

At this point, you’ll have a regular var val: IUnknown; which will ofc do memory management for you as it should. :slight_smile:

1 Like