5

インターフェイスを返す関数をエクスポートする dll があります。

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

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

このラッパーは、DLL を遅延ロードし、GetInterface が初めて呼び出されたときに、エクスポートされた関数のモジュール ハンドルと proc アドレスをキャッシュします。FreeLibrary への呼び出しは、ラッパーのデストラクタで発生します。

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

どうすればこれを優雅に処理できますか?本格的な COM 実装は、このシナリオをどのように処理しますか?

4

1 に答える 1

5

COM は、責任を DLL に移すことでこの問題を処理します。DLL は、 という名前の関数を実装してエクスポートする必要がありますDllCanUnloadNow。COM がときどき呼び出し、true を返す場合は、DLL がアンロードされている可能性があります。

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

同じテクニックを使用できます。GetInterface関数が何を出力し、何がリリースされたかを追跡します。別の関数をエクスポートして、ホスト プログラムがライブラリを安全にアンロードできるかどうかを確認できるようにします。

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

于 2013-08-14T03:22:56.583 に答える