Delphi 基本插件框架

Delphi 基本插件框架,delphi,plugins,Delphi,Plugins,我必须为我正在开发的非gui应用程序开发插件系统。我设想这是一个核心应用程序,它有一套基本的功能,并且可以通过插件进行扩展 现在,我发现最好的方法可能是将插件制作成DLL,并在主机应用程序中加载它们。插件应该能够修改appcore的某些部分(访问某些方法/变量),这是一个棘手的部分 我的想法是创建THost类,它实现IHost和IHostExposed接口。当主机加载插件时,它会将IHostExposed传递给插件,插件可以调用方法/访问该接口中的变量。大概是这样的: 接口声明: unit uH

我必须为我正在开发的非gui应用程序开发插件系统。我设想这是一个核心应用程序,它有一套基本的功能,并且可以通过插件进行扩展

现在,我发现最好的方法可能是将插件制作成DLL,并在主机应用程序中加载它们。插件应该能够修改appcore的某些部分(访问某些方法/变量),这是一个棘手的部分

我的想法是创建
THost
类,它实现
IHost
IHostExposed
接口。当主机加载插件时,它会将
IHostExposed
传递给插件,插件可以调用方法/访问该接口中的变量。大概是这样的:

接口声明:

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.
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

  ...
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); 

      ...
主机类声明:

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.
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

  ...
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); 

      ...
…我将如何使用它:

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.
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

  ...
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); 

      ...
类型
TRegisterPlugin=过程(const ahosexposed:ihoosexposed);
变量
hdll:THandle;
RegisterPlugin:TRegisterPlugin;
主持人:IHost,;
开始
主机:=THost.Create;
hdll:=LoadLibrary('plugin.dll');
如果hdll为0,则
开始
@RegisterPlugin:=GetProcAddress(hdll,'RegisterPlugin');
如果已分配(RegisterPlugin),则
开始
//调用插件函数并将IHostExposed接口传递给它
//从那个里开始,插件可以使用这个接口与核心应用程序进行交互
RegisterPlugin(如我所透露的主机);
...

我想听到的是关于这种方法的任何建议,以及是否有更好的解决方案来实现我的目标?

显然您以前使用过接口,但您不知道COM的组件注册功能?使用“新建项目向导”启动包含自动化对象的ActiveX库,查看类型库编辑器,并查看库运行和注册时会发生什么(都在System.Win.ComServ.pas中)

显然您以前使用过接口,但不知道COM的组件注册功能?使用“新建项目向导”启动包含自动化对象的ActiveX库,查看类型库编辑器,并查看库运行和注册时会发生什么(都在System.Win.ComServ.pas中)

这实际上是我第一次使用接口。谢谢,我来看看ComServ.past这实际上是我第一次使用接口。谢谢,我将查看ComServ.pas