Динамически подгружаемые библиотеки

maomao
отредактировано 23:40 Раздел: FastScript
Желаю странного...
Хочется использовать подгружаемые библиотеки для формирования новых возможностей внутри проекта. Т.е. основная мысль такая: пишется ядро системы, которое умеет подгружать BPL через LoadPackage. Внутри LoadPackage вызывается Initialization, который умеет делать, например:
initialization
  Functions := TFunctions.Create;
где, в свою очередь, делается:
constructor TFunctions.Create;
begin
  with fsGlobalUnit do
  begin
    AddedBy := Self;

    with AddClass(TCommonDialog, 'TComponent') do
      AddMethod('function Execute: Boolean', CallMethod);
    AddClass(TOpenDialog, 'TCommonDialog');
    AddClass(TSaveDialog, 'TCommonDialog');
    AddClass(TColorDialog, 'TCommonDialog');
    AddClass(TFontDialog, 'TCommonDialog');

    AddedBy := nil;
  end;
end;
Таким образом хочется написать ядро, и больше его не исправлять (компилировать, переустанавливать и т.д.), а дописывать библиотеки.

НО!!!
Получается очень нехорошая вещь, когда пишешь ядро и делаешь статическую линковку bpl, то все ОК (классы, функции и пр. видны в fsGlobalUnit), а когда подгружаешь через LoadPackage - то для каждой подружаемой bpl создается свой fsGlobalUnit. Господа-разработчики FS, поясните: это так задумано, или дело в моих руках?

Вот код тестового приложения:
EXE
program fstst;

uses
  Forms,
  mfstst in 'mfstst.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
unit mfstst;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, fs_tree;

type
  TForm1 = class(TForm)
    fsTree1: TfsTree;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  LoadPackage('C:\Program Files\Borland\Delphi6\Projects\Bpl\fstst_pkg.bpl');
  fsTree1.UpdateItems;
end;

end.
dfm
object Form1: TForm1
  Left = 192
  Top = 107
  Width = 783
  Height = 540
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object fsTree1: TfsTree
    Left = 0
    Top = 0
    Width = 775
    Height = 513
    Align = alClient
    BevelOuter = bvNone
    Caption = 'fsTree1'
    TabOrder = 0
    ShowClasses = True
    ShowFunctions = True
    ShowTypes = True
    ShowVariables = True
    Expanded = True
    ExpandLevel = 2
  end
end
и соотвественно bpl:
package fstst_pkg;

{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$RUNONLY}
{$IMPLICITBUILD OFF}

requires
  rtl,
  vcl,
  fs6;

contains
  fs_tstrtti in 'fs_tstrtti.pas';

end.
unit fs_tstrtti;

interface

{$i fs.inc}

uses
  SysUtils, Classes, fs_iinterpreter, fs_iclassesrtti, dialogs;

type
  TfsTstRTTI = class(TComponent); // fake component


implementation

type

  TFunctions = class(TObject)
  private
    function CallMethod(Instance: TObject; ClassType: TClass;
      const MethodName: String; var Params: Variant): Variant;
  public
    constructor Create;
    destructor Destroy; override;
  end;

var
  Functions: TFunctions;


{ TFunctions }

constructor TFunctions.Create;
begin
  with fsGlobalUnit do
  begin
    AddedBy := Self;

    with AddClass(TCommonDialog, 'TComponent') do
      AddMethod('function Execute: Boolean', CallMethod);
    AddClass(TOpenDialog, 'TCommonDialog');
    AddClass(TSaveDialog, 'TCommonDialog');
    AddClass(TColorDialog, 'TCommonDialog');
    AddClass(TFontDialog, 'TCommonDialog');

    AddedBy := nil;
  end;
end;

destructor TFunctions.Destroy;
begin
  if fsGlobalUnit <> nil then
    fsGlobalUnit.RemoveItems(Self);
  inherited;
end;

function TFunctions.CallMethod(Instance: TObject; ClassType: TClass;
  const MethodName: String; var Params: Variant): Variant;
var
  s: String;
begin
  Result := 0;
end;



initialization
  Functions := TFunctions.Create;

finalization
  Functions.Free;

end.

Комментарии

  • отредактировано 23:40
    Нужно компилировать exe со внешним package FastScript, иначе в EXE и в BPL будут свои собственные экземпляры fsGlobalUnit.
  • maomao
    отредактировано 23:40
    Не хочу показаться лохом позорным, но делаю именно с runtime packages ;)
    Я пример написал для Delphi, хотя живое, большое приложение живет в CBuilder ессно с packages. Я пробовал различные варианты - даже передачу указателя fsGlobalUnit в подгружаемый BPL, все равно получается какая-то фигня. Если у кого нибудь есть работающий пример киньте им в меня на m_a_o@mail.ru

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.