2009-03-19 3 views
5

私はthis articleを読んで、DLLのランタイム読み込みに最適な仮想ライブラリインターフェイスの概念を見つけました。しかし、Win32では利用できないようです。これは本当ですか?もしそうなら、なぜですか?私はアイデアを.NETに結びつけるものは見ません。Delphi/Win32の仮想ライブラリインタフェース?

編集:私はここでは、Robがすでに書いたことをここでは言い換えています。 :-)
私はプラグインやそれに類するものではありません。それは普通の古いWin32 DLLです。 DLLにあるすべての関数に対してGetProcAddressを呼び出す必要はなく、コンパイラに実行時にDLLをロードする詳細をすべて処理させるというアイデアです。

答えて

6

これまで3つの回答が完全にあなたの質問のポイントを逃したようです。それ、または私は持っています。あなたはなぜWin32 Delphiに魔法のようなものがないのかを尋ねています。Supports関数はHallvardの記事でお話しますね。つまり、DLLの名前とインタフェースの型情報が与えられた場合、DLLからエクスポートされたスタンドアロン関数を使用して、そのインタフェースを実装するオブジェクトを返します。

Hydraは、DLLから関数をインポートするのではなく、Win32プログラムから.Netコードを呼び出すことに関するすべてのようです。 TJvPluginManagerでは、プラグインDLLが、DLLをロードするときにマネージャが呼び出す特別な自己登録機能をエクスポートする必要があり、その機能はTJvPluginクラスのインスタンスを返さなければならないため、プラグインDLLはDelphiまたはC++ Builder。一方、Supports関数は、任意の言語で書かれたDLLで動作します。必要に応じて、kernel32で使用することができます。

Win32 Delphiにこのようなことがない理由はわかりません。 DelphiとTurbo Pascalがなくても、CodeGearはすでにそれほど長い間要求を受けていなかったかもしれません。

Microsoftの.Netライブラリが既にほとんどの部分を提供していない限り、.NET版よりも書くのが難しいとは思っていません。 Delphiは、Delphiが長年にわたって持っていたSupportsのいくつかの他のオーバーロードされたバージョンのように見える、便利なコール関数にそれらをラップします。

Win32でその機能を実装するには、いくつかの手順があります。 (私はDelphiの実行中のコピーを現在持っていないので、必要なものだけを提供しています。うまくいけば、もっと詳しく知ることができます)。まず、タイプを確認する必要があります少なくともメソッドの装飾されていない名前を保持するインターフェースの情報。次に、Supportsは、インターフェイス内の各メソッド(_AddRef、_Release、QueryInterface以外)の関数スタブを生成する必要があります。スタブは、呼び出し規約がstdcallであると仮定すると、このような何かを行くだろう:

asm 
    // Pop the return address, 
    // discard the "this" pointer, 
    // and restore the return address 
    pop eax 
    pop ecx 
    push eax 

    jmp AddressOfFunction 
end; 

Supportsように、各スタブを生成し、それは、対応するインターフェイスメソッドの名前でGetProcAddressを呼び出すから得実際の関数アドレス、記入う。 stdcall呼び出し規約は、そのように折り返すのは簡単です。 cdeclはちょっと面倒です。 registerは首の痛みです。

すべてのスタブが生成されたら、指定されたインタフェースを実装するように見える「オブジェクト」を生成する必要があります。それは実際のクラスである必要はありません。コンパイル時に、Supportsは、実装するように頼まれる予定のインターフェースのレイアウトを知らないので、クラスを持っていてもそれほど成果は上がりません。

最後のステップは、_AddRef,_ReleaseおよびQueryInterfaceの実装を提供することです。 _AddRefは目立たないでしょう。 _Releaseは、参照カウントがゼロに達したときにFreeLibraryと呼ぶ場所です。 QueryInterfaceは、IUnknownをサポートし、インターフェイスがSupportsに指定されていることを除いて、まったく役に立たないでしょう。

デルファイでは、クラスなしでインターフェイスを実装することを実証したサンプルプログラムが付属していました。レコードと関数ポインタ(すべてのインターフェイスは最終的には結局のところです)ですべてが完了しました。 Delphiには、クラスでそれを行うための対応するコードが付属していました。私は今デモプログラムの名前を見つけることができませんが、私はそれがまだどこかにあると確信しています。

+0

私はそれを私の回答で簡潔に述べました。これは私が行きたくないものの「ポインタを使って邪魔になる」ものです。ああ、そしてサイドボーナスとして、それはまた組立のまわりで醜いmuckingを含む。私はその部分を忘れてしまった! :P –

+0

実際にはアセンブリではありません。マシンコード。私が上に書いたアセンブリは説明のためのものです。実行時にコードを生成するため、マシンコードを直接記述する必要があり、実行時アセンブラは使用できません。 –

+0

+1、思いやりのある答え、技術的な詳細の素敵な説明。それを書く時間をとってくれてありがとう。 – mghie

3

このタイプにはいくつかのWin32オプションがありますの機能Project JEDIには、DLLやパッケージのいずれかをロードするJVCLの一部としてのオープンソースプラグインシステムがあり、フォームやその他の機能を追加機能として含めることができます。

TMS Plugin FrameworkおよびRemObjects Hydraを含む数多くの市販製品もあります。

1

これは新しいものでも特別なものでもありません。この記事ではプラグインについて話しています。ネイティブコードは何年もプラグインを実行できました。 P/Invokeの唯一の特殊な点は、ネイティブコードと.NETがプラグインシステムでお互いに話すことができることと、「DLLはインターフェイスを実装するシングルトンオブジェクトとして見ることができる小さなトリックです。 Borland.Delphi.Win32ユニットのSupports関数を使用して、DLLとすべてのメソッドが利用可能かどうかを確認することができます。

Delphi for Win32で記事の内容を説明したい場合は、LoadLibrary、GetProcAddress、およびFreeLibrary Windows API関数を参照してください。記事の説明のようなインターフェイスが絶対必要な場合は、インターフェイスを返すエクスポートされた関数を記述するか、DLLを書き込むか、呼び出し元のアプリケーションでGetProcAddressを使用してインターフェイスを動的に作成する関数です。 (注意:これはポインタを使って回避する必要があり、通常はそれ以上の問題です)

おそらく、Tim Sullivanの言葉通りです:ネイティブコードが必要な場合はJEDI VCLからTJvPluginManagerを使用するか、 Hydra .NETアセンブリと対話する必要がある場合。

0

私はHydraをDelphi専用のソリューション(つまり、.NETとのインターフェイスを持たない)に使用しています。それは使用する方が簡単だし、いくつかの細かな点を追加し、私はそれが基本的に、この記事ではよく記述されている「ロール自分で自分の」プラグインフレームワークと同じように実装だと思う:私は探します http://www.saxon.co.uk/SinglePkg/

をプラグインのフレームワークは、アプリケーション間で単にメッセージを送信するのではなく、インターフェースベースのもの(Hydraや上記の「ロール・ツー・オーダー」のシステムなど)です。

SourceForgeのDelphiのプラグインフレームワークがあり、JEDIプロジェクト内かどうかと、それは同じものですかどうかわからないが:http://sourceforge.net/projects/rd-dpf

Dragonsoftのそのうちの1つは、他の商用ソリューションのカップルは、もあります。 http://www.dragonsoft.us/products_dsps.php

0

シンプルなCOMオブジェクトでこれを行うと何が問題になりますか?すべてのプラグインが実装するシンプルなインタフェースを宣言し、各comオブジェクトにそのクラスのGUIDを返すエクスポートされた関数を含める必要があります。その後、 "plugins"を使用するのは、特別な登録機能を公開しているDLLを探しているプラ​​グインディレクトリを歩き回り、それを呼び出してからクラスGUIDを使用してcomオブジェクトを呼び出すのと同じくらい簡単です。

私はこのようなものをWIN32の商用アプリケーションで大成功を収めて使用しました。利点は、プラグインを自由に入れ替えることができたことです(もちろん、アプリケーションは既存のアプリケーションを削除するために実行されていませんでしたが)。

+0

これは基本的に、TJvPluginManagerがフードの下で動作する方法ですが、COMの代わりにいくつかのトリックがあります。 –

+0

関数を呼び出すDLLは、必ずしもCOMオブジェクトをエクスポートするとは限りません。私は本当に混乱しています:どこに他の人がUlrichがプラグインを求めているという考えを得たのですか? –

+0

関数はcomオブジェクトをエクスポートしません.dll内のcomオブジェクトのインスタンスにアクセスするために必要なGUIDのみを返します。はい、そのプラグインは、ポイントthats。実行時と遅いバインディングで機能を追加すると、確かにプラグインのarchtectureのように聞こえる。 – skamradt