2013-08-13 31 views
5

Interfaceを返す関数をエクスポートするDLLがあります。FreeLibraryが呼び出される前にInterfaceインスタンスが解放されるようにする方法

エクスポートされた関数を呼び出すために使用されるLoadLibrary、GetProcAddress、およびFreeLibrary関数のラッパーを作成しました。

TInterfaceGetter = class 
private 
... 
public 
    constructor Create; 
    destructor Destroy; override; 
    function GetInterface: IMyInterface; 
end; 

怠惰なこのラッパーは、DLLをロードし、GETINTERFACEが初めて呼び出されたときにモジュールハンドルおよびエクスポート機能のprocのアドレスをキャッシュします。 FreeLibraryの呼び出しは、ラッパーのデストラクタで行われます。

ラッパーを解放した後にクライアントコードがインターフェイス参照にハングする場合を除いて、すべてがうまく動作します。インターフェイスの参照が最終的に有効範囲外になると、_IntfClearの呼び出しによって、dllおよび使用されているすべてのメモリがクライアントのメモリ空間から既にアンロードされているため、アクセス違反が発生します。

これをどのようにして正常に処理できますか?完全な吹き飛ばされたCOM実装は、このシナリオをどのように処理しますか?

答えて

6

COMは、責任をDLLに移すことによってこの問題を処理します。 DLLは、DllCanUnloadNowという名前の関数を実装してエクスポートする必要があります。 COMは時折この呼び出しを行い、TRUEを返すと、DLLがアンロードされることがあります。

関数はどのように知っていますか? DLLは、DllGetClassObjectへの呼び出しによっていくつのオブジェクトを出したかを追跡し、それらのオブジェクトのうちどれだけがまだ生存しているかを知っています。 DelphiのデフォルトCOM DLL実装では、各オブジェクトが独自の参照カウントを保持する方法と同様に、グローバルオブジェクト数を維持します。たとえば、ComServ.pasの実装を参照してください。

同じ手法を使用できます。あなたのGetInterface機能が提供するものとリリースされたものを追跡します。別の関数をエクスポートして、ホストプログラムがライブラリをアンロードするのが安全かどうかを尋ねることができます。

代替方法は、DLLを実際のCOM DLLに変更することです。

関連する問題