2011-01-11 7 views
5

いくつかの関数を共有DLLに移動しています(Windowsフックとして呼びたいものがあります)。DLL内のdelphi finalizalizationコード

実際の機能は現在unitにあり、何らかの形でinitializationfinalizationのコードがあります。

私は当初、unitからlibraryに直接変換することを考えていました。そこで私はbeginend.の間にinitializationコードを移動しました。しかし、私はfinalizationコードを移動する場所がないことに気付きました。代わりに特別なDLLエントリポイントを作成して登録する必要があります。

私の質問です。 unitのすべての機能と、initializationfinalizationのコードを残して、usesの単位を持つlibraryスタブを作成するだけですか?それはfinalizationと呼ばれますか?

答えて

8

DLL内のユニットの初期化セクションのコードは、DLLが最初にプロセスにロードされたときに実行されます。ファイナライズセクションは、DLLがプロセスからアンロードされると起動します。

Eugeneは、DLLProcを使用してより細かい制御を行うことができますが、通常、スレッド単位のリソース(例:スレッドローカルストレージ。

DLLMainの中で何ができるのかには深刻な制限がありますが、これは最終的にこれらの初期化/ファイナライズのセクションがライブラリ内で発生した場所であることを指摘します。 MSDNのドキュメントには、基本的にいくつかのことができると書かれていますが、受け入れ可能な動作のリストはありません。カーネル32で関数を呼び出すことができるということに最も近いのです。それ以外の場合は、すべての賭けはオフです!

ウェブ上にこの問題を説明する記事がたくさんありますが、上記でリンクしたDLLMainのMSDNトピック以外にも、MicrosoftのBest Practices for Creating DLLsを読むことをお勧めします。

MSDNが提供する有用なアドバイスは、DLLを使用する前にユーザーが初期化関数を呼び出すことをライブラリが要求できるということです。対応するファイナライズ関数は、DLLを終了すると呼び出されます。 comctl32.dllを使用すると、このイディオムが使用されます(InitCommonControlsExを参照)。

私自身のコードでは、私は別のアプローチを好みます。すべての私のユニットの初期化セクションは、初期化とファイナライズメソッドを登録します。次に、ライブラリからエクスポートされた関数への最初の呼び出しで、初期化メソッドが登録された順に実行されます。これは私のライブラリーへのすべてのエントリー/出口ポイントをすでに制御しているので、実装するのは問題ではありません。

これはあなたが求めている以上のものですが、問題をデバッグするのがむしろ難しいことを避けると便利な場合があります。

+2

+1。要するに、ファイナライゼーションセクション*のコードが呼び出されますが、OSローダーロックのために、あなたはそれを望まないかもしれません。デッドロックの回避:ホストプロセスが呼び出すための明示的な初期化と終了関数をエクスポートする。 –

+0

The Old New Thingが理由を説明します:http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx –

+2

@Jeroen私はその記事にリンクするつもりでしたが、それは少しですキュレーターの卵とレイモンドがリンクしている記事は、MSリンクの腐敗によって食べられたように見えます。私が見つけた最高のリファレンスはhttp://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx –

4

ユニットの初期化は、そのプログラムとそのライブラリの場合に呼び出されます。

ファイナライズと同じです。

はい、そのままにして、必要な機能をエクスポートすることができます。

0

私は、DLLMainを実装し、状況ごとに専用のプロシージャ/関数を呼び出すことで、さまざまな状況(プロセスのアタッチ、スレッドのアタッチなど)を処理することをお勧めします。その後、DLLからユニットに切り替える必要がある場合、初期化とファイナライズから必要なプロシージャ/関数を呼び出すことができます。なぜなら、DLLをスレッドに接続/切り離し(システム全体のフックを設定したときに発生する)には、きめ細かな制御が必要な場合があるからです。

+0

あなたはそうすべきではありません。そしてThe Old New Thingは理由を説明します:http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx –

+0

@Jeroenこれはすべての言葉です。実際、多くの場合、システム全体のフックを実装すると、多くの場合、DLLMainを使用してスレッドの添付ファイルを追跡する必要があります。これはシステム全体のフックの性質によるものです。 –

0

これは私にも起こります。 私は、dllが登録されたときに、スレッドを作成するか、何かをする初期化セクションを持っていることが分かりました。

私はこの初期化セクションを削除して正常に動作しました。

初期化が.exeのアプリケーションのためにではなく、DLLをアプリケーションに要求される、ので、 システムユーティリティで変数のフラグがModuleIsLib と呼ばれ、そこにあるだけで実行します。

initialization 

if not ModuleIsLib then 
begin 
// initialization stuff for .exe file 
end; 

これがためにも行うことができますファイナライゼーションセクションも同様です。

願っています!

関連する問題