1

I have to develop plugin system for non-gui app that I'm developing. I envisioned this as core app that has basic set of features, and which is extendable with plugins.

Now, I figured out that probably best way to do this is to make plugins as DLLs, and to load them within host app. Plugins should be able to modify some parts of app core (access to certain methods/variables), and this is tricky part.

What I've thought is to make THost class, which implements IHost and IHostExposed interfaces. When host loads plugin, it will pass IHostExposed to plugin, and plugin could call methods/access to variables in that interface. Something like this:

Interface declarations:

unit uHostInterfaces;

interface

type
  IHost = interface
  ['{BAFA98BC-271A-4847-80CE-969377C03966}']
    procedure Start;
    procedure Stop;
  end;

  // this intf will get exposed to plugin
  IHostExposed = interface 
  ['{1C59B1A9-EC7A-4D33-A574-96DF8F5A7857}']
    function GetVar1: Integer;
    function GetVar2: String;

    procedure SetVar1(const AValue: Integer);
    procedure SetVar2(const AValue: String);

    property Var1: Integer read GetVar1 write SetVar1;
    property Var2: String read GetVar2 write SetVar2;
  end;

implementation

end.

Host class declaration:

unit uHost;

interface

uses
  Winapi.Windows, Winapi.Messages,
  uHostInterfaces, uInstanceController, uSettings;

type
  THost = class(TInterfacedObject, IHost, IHostExposed)
  private
    FVar1              : Integer;
    FVar2              : String;

    FWindowHandle      : HWND;
    FInstanceController: TInstanceController;
    FSettings          : TSettings;

    procedure WndProc(var AMessage: TMessage);

  public
    constructor Create;
    destructor Destroy; override;

    // methods from IHost
    procedure Start;
    procedure Stop;

    // methods from IHostExposed, which get set Var1/Var2
    function GetVar1: Integer;
    function GetVar2: string;

    procedure SetVar1(const AValue: Integer);
    procedure SetVar2(const AValue: string);
  end;

  implementation

  ...

...and how i'd use it:

type
  TRegisterPlugin = procedure(const AHostExposed: IHostExposed);

var
  hdll          : THandle;
  RegisterPlugin: TRegisterPlugin;
  host          : IHost;

begin
  host := THost.Create;

  hdll := LoadLibrary('plugin.dll');
  if hdll <> 0 then
  begin
    @RegisterPlugin := GetProcAddress(hdll, 'RegisterPlugin');
    if Assigned(RegisterPlugin) then
    begin
      // call the plugin function and pass IHostExposed interface to it
      // from there on, plugin can use this interface to interact with core app
      RegisterPlugin(host as IHostExposed); 

      ...

What I would like to hear is any suggestions about this approach, and if there are better solutions for what I'm trying to achieve?

4

1 に答える 1

1

以前にインターフェイスを扱ったことがあるようですが、COM のコンポーネント登録機能については知りませんか? 新しいプロジェクト ウィザードを使用して、オートメーション オブジェクトを含む ActiveX ライブラリを開始し、タイプ ライブラリ エディタを調べて、ライブラリが実行されて自身が登録されるとどうなるかを確認します (すべて System.Win.ComServ.pas にあります)。

于 2013-10-15T16:47:52.393 に答える