4

私は、BPL を動的にロードし、オブジェクト インスタンスをメイン アプリから BPL のメソッドに渡すというアイデアをいじっていました。これにより、アプリケーションで使用されるユニットと BPL で使用されるユニットの間で問題が発生します。

私はこれを行う小さなプロトタイプを作成し、Delphi がアプリで定義されたクラスと BPL で定義されたクラスの間の違いを内部的にどのように管理しているかに興味を持っていました。

たとえば、次のような基本的な Widget クラスがあるとします。

TmyWidget = class
private
  fId:Integer;
  fDescription:String;
public
  procedure DoSomething1();
end;

これで、TmyWidget クラスを含むユニットを使用して、アプリと BPL がビルドされました。その後、TMyWidget で何かが変更され、アプリが再構築されましたが、BPL はそうではありません (またはその逆です)。別のメソッド DoSomething2() を追加し、アプリで TmyWidget のインスタンスを作成し、処理のために BPL に渡しました。基本的な例、うまくいきました。しかし、それは明らかに潜在的な問題をはらんでいます。

動的にロードされる別の BPL も TmyWidget を使用する場合、事態はさらに興味深いものになります。機能しているように見えますが、理想的ではありません。

主な質問は、通常、メイン アプリケーションと DLL または BPL との間でオブジェクトをどのように受け渡すかということです。これまでに試みたことはなく、おそらく正当な理由がありますが、このアプローチに役立つこのアイデアを思いつきました...

最良のアプローチは、オブジェクトをシリアル化し、それらのバイトを渡し、DLL/BPL で逆シリアル化することだと思いますが、このプロセスでは、ホストと動的に読み込まれるモジュールの間の潜在的なバージョンの違いに注意を払っていますが、新しい SimpleSharedMem を望んでいましたオプションは、シリアル化のオーバーヘッドなしでこの新しい機能をもたらす可能性がありますが、共有コードの変更に合わせてアプリと dll を再構築することを厳密に維持しない限り、あまり役に立たないようです...しかし、このプロトタイプでは、アプリはかなり一定のままですまた、動的にロードされるモジュールは、TmyWidget に機能が追加されて頻繁に変更されます。(サーバー アプリは、クライアントの要求に基づいて TmyWidget を構築するためのファクトリとして機能し、アプリは処理のためにさまざまなモジュールにインスタンスを渡します。)

4

2 に答える 2

10

...Delphi がアプリで定義されたクラスと BPL で定義されたクラスの違いを内部的に管理する方法に興味がありました

Delphi は、許可しないことでこれを管理します。同時に複数のパッケージで同じ名前のユニットを使用することはできません: その場合、次のようなエラー メッセージが表示されますPackage XYZ already contains ABC(しばらく見ていませんでした...)。タイプ名にはユニット名が含まれるため、2 つの異なるパッケージに同じタイプを含めることはできません。それが GUID によって定義されたインターフェイスでない限り、それは別の話です。

... 通常、メイン アプリケーションと DLL または BPL との間でオブジェクトをどのように受け渡しますか?

オブジェクトを DLL に渡さないでください。これはお勧めできません。オブジェクトを BPL に渡す必要がある場合は、その BPL の基本クラスが 3 番目の BPL に定義されていることを確認してください。

例。ポリモーフィックな動作は、TmyWidgetおそらくいくつかの仮想メソッドを使用して定義されています。TmyWidgetBaseこれらのすべての仮想メソッドを定義するクラスがあることを確認しTmyWidget、その基本クラスからすべての を派生させ、タイプのオブジェクトを渡しますTmyWidgetBaseTmyWidgetBaseクラスが独自のパッケージに含まれていることを確認してください。

これをやろうとすると、小さな「ブートストラップ」exe とたくさんの BPL ができてしまいました。オブジェクトの受け渡しを容易にするために、基本的にすべてのロジックは BPL にありました。

于 2011-03-09T16:26:01.307 に答える
7

私が取り組んできたプロジェクトの 1 つは、10 年以上にわたって多数のランタイム パッケージをうまく使用してきたので、パッケージを扱った私の経験のいくつかを共有します。

Cosmin が指摘したように、異なるパッケージに同じユニットを含めることはできません。別のパッケージのrequires句にパッケージを追加するか、プロジェクト オプションのランタイム パッケージリストにパッケージを追加することにより、暗黙的なリンクを使用する場合、コンパイラは作業を行い、次のエラー メッセージのいずれかを報告します。

E2199: Packages '%s' and '%s' both contain unit '%s'(同じユニットを含む 2 つのパッケージに依存するコンパイル プロジェクトの場合)

E2200: Package '%s' already contains unit '%s'(ユニットを含むパッケージをコンパイルする場合、これは依存するパッケージの1つにすでに含まれています)

LoadPackage を使用して明示的なリンクを使用している場合は、通常、ランタイムでチェックが試行され (回避される可能性があります)、次のエラーが発生します。

EPackageError: パッケージ '%s' を読み込めません。パッケージ '%s' にも含まれているユニット '%s' が含まれています

これらのエラーを解決することは、それほど難しいことではありません。

両方ともユニットを使用する必要がある 2 つのパッケージがある場合は、そのうちの 1 つにユニットを含め、もう 1 つのパッケージに最初のユニットを含めるようにします。 パッケージの依存関係グラフ

互いに含まれているユニットを使用する必要がある 2 つのパッケージがある場合、それらのユニットを、両方が依存できる新しいパッケージに移動する必要があります。 依存関係グラフ

暗黙的にリンクされたパッケージには、静的にリンクされているかのようにクラス定義に直接アクセスできるという利点があります。ユニットを使用する必要があるユニットの uses 句にユニットを追加するだけです。コンパイラとランタイム環境がすべてを解決します。

明示的にリンクされたパッケージは、初期化セクションのクラス登録に依存する必要があります。

于 2011-03-10T17:35:32.310 に答える