What is the correct way to free the interface for OleVariant?

I am trying to find a safe / deterministic way to free an interface that is enclosed in OleVariant.

AFAICS Delphi frees up interface references at the end of the procedure, but in my case I have to do this before because I need to disable COM.

procedure Test; var LLibrary: OleVariant; begin CoInitialize(nil); try LLibrary := Null; try LLibrary := CreateOleObject(LibraryName); finally LLibrary := Unassigned; // <-- I would like to release the interface here end; finally CoUninitialize; // <-- Shutdown of COM end; end; // <-- The compiler releases the interface here 

I believe that to add OleVariant to an instance of an additional class, I can free myself before calling CoUninitialize .

 procedure Test; var Container: TLibraryContainer; // Holds the OleVariant begin CoInitialize(nil); try Container := TLibraryContainer.Create; try {...} finally Container.Free; end; finally CoUninitialize; end; end; 

Is this solution safe or is there a better solution that I have missed?

+8
delphi delphi-2007 com finalization
source share
1 answer

The compiler explicitly uses the implicit local interface variable for the return value from CreateOleObject . Then it is released at the end of the procedure, too late for you.

There are several ways to defeat this. First of all, you can explicitly specify a reference to the IDispatch interface returned by CreateOleObject . This allows you to control your life time.

 procedure Test; var intf: IDispatch; LLibrary: OleVariant; begin CoInitialize(nil); try intf := CreateOleObject(LibraryName); try LLibrary := intf; finally VarClear(LLibrary); intf := nil; end; finally CoUninitialize; end; end; 

An alternative would be to move the code that called CreateOleObject to a separate routine with its own scope.

 procedure DoWork; var LLibrary: OleVariant; begin LLibrary := CreateOleObject(LibraryName); //do stuff with LLibrary end; procedure Test; begin CoInitialize(nil); try DoWork; finally CoUninitialize; end; end; 

Since the implicit local link is within DoWork , it is freed at the end of DoWork and therefore before running CoUninitialize .

My recommendation is to use the second option, which is cleaner and forces the compiler to do the work on your behalf.

+9
source share

All Articles