Аналоги LoadPackage() и UnloadPackage()

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Аналоги LoadPackage() и UnloadPackage()

Сообщение MuHbKa » 22.08.2008 14:08:50

На Delphi я храню объекты проекта в виде *.bpl, описание объектов (имя модуля, имя класса, стиль формы и т.д.) хранится в БД.
Модули гружу в память LoadPackage() и выгружаю UnloadPackage() по мере использования.
В исходниках Lazarus этих процедур не обнаружил.
Что посоветуете?

PS: Ниже исходник дельфого модуля. TBaseForm это базовый клас от которого порождены все формы проекта.
Код: Выделить всё
unit Dispatcher;

interface

uses Windows, Controls, Messages, Classes, Base;

const
  InnerDatabaseName = 'DB';

  CM_LOAD_OBJECT = WM_USER + 100;
  CM_UNLOAD_OBJECT = WM_USER + 101;

  oiSysQuery = 0;

type
  TObjectType = (otStartupForm, otForm, otComponentSet);

  TBaseFormClass = class of TBaseForm;

function LoadObject(aModuleName, aClassName: string; Params: TStrings): TBaseForm;
procedure UnloadObject(aModuleName: string);
procedure CallDispatcher(ObjectID: Integer; ObjectParams: TStrings; Container: TWinControl);
function GetAppPath: string;

var
  LoadedObjectList: TStringList;

implementation

uses DBTables, SysUtils, Forms, StdCtrls, Dialogs, Variants, ObjectParamsViewer;

function LoadObject(aModuleName, aClassName: string; Params: TStrings): TBaseForm;
var
  Handle: Integer;
begin
  Result := nil;

  Handle := LoadPackage(aModuleName);
  LoadedObjectList.Values[aModuleName] := IntToStr(Handle);
  if Assigned(Params) then Params.Values[aModuleName] := IntToStr(Handle);

  if LoadedObjectList.Values[aModuleName] <> '' then begin
     Result := TBaseFormClass(FindClass(aClassName)).Create(Application);
     if Assigned(Result) then
        if Result.InitParams(Params) then
           Result.FormStyle := TFormStyle(StrToIntDef(Params.Values['FORM_STYLE'], 0))
        else
           Result.Free
     else
        UnloadObject(aModuleName);
  end;
end;

procedure UnloadObject(aModuleName: string);
begin
  with LoadedObjectList do begin
    UnloadPackage(StrToInt(Values[aModuleName]));
    Delete(IndexOfName(aModuleName));
  end;
end;

procedure CallDispatcher(ObjectID: Integer; ObjectParams: TStrings; Container: TWinControl);
var
  BaseForm: TBaseForm;
  I: Integer;
  Temp: TControl;
begin
  if not Assigned(ObjectParams) then ObjectParams := TStringList.Create;

  if ObjectParams.Strings[0]<>'[ClassParams]=' then
    ObjectParams.Insert(0,'[ClassParams]=');
  ObjectParams.Values['[ObjParams]']:=' ';

  with TQuery.Create(nil) do
    try
      DatabaseName := InnerDatabaseName;
      SQL.Add('select * from get_object_params(:p_object_id)');
      ParamByName('p_object_id').asInteger := ObjectID;
      Open;
      while not EOF do begin
        ObjectParams.Values[FieldByName('name').asString] := FieldByName('param_value').asString;
        Next;
      end;
      Close;
    finally
      Free;
    end;

   if (GetAsyncKeyState(VK_LSHIFT) and $80000000) = $80000000 then begin
     with TParamViewerForm.Create(Application) do begin
       ObjParams.AddStrings(ObjectParams);
       if ShowModal=mrOK then begin
         ObjectParams.Clear;
         ObjectParams.AddStrings(ObjParams);
         ObjParams.Free;
         end;
//           Application.MessageBox(PChar(ObjectParams.Text), PChar(Application.Title), MB_ICONINFORMATION + MB_OK);
       free;
     end;
   end;

  with ObjectParams do begin
    BaseForm := LoadObject(Values['MODULE_NAME'], Values['CLASS_NAME'], ObjectParams);
    if BaseForm <> nil then begin
       with BaseForm do
         case TObjectType(StrToInt(Values['OBJECT_CLASS'])) of
           otStartupForm, otForm:
             case FormStyle of
               fsNormal: begin
                 if Assigned(Container) and (Container is TBaseForm) then
                    TBaseForm(Container).OnCall(BaseForm);
                 if Values['FORM_SHOW'] <> '0' then ShowModal;
               end;
               fsStayOnTop: Show;
             end;
           otComponentSet: begin
             if Container <> nil then
                for I := ControlCount - 1 downto 0 do begin
                  Temp := Controls[i];
                  RemoveControl(Temp);
                  Container.InsertControl(Temp);
                end;
           end;
         end;
       PostMessage(Application.Handle, CM_LOAD_OBJECT, 0, Integer(BaseForm));
    end;
  end;
end;

function GetAppPath: string;
begin
  Result := ExtractFileDir(Application.ExeName);
end;

initialization
  LoadedObjectList := TStringList.Create;

end.
Аватара пользователя
MuHbKa
незнакомец
 
Сообщения: 4
Зарегистрирован: 22.08.2008 13:08:57
Откуда: Тольятти

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение alexs » 22.08.2008 15:10:06

ну так как пакетов в fpc пока нет - то 2 пути:
1. Используй DLL - но это черевато тем, что dll будут очень большими (надеюсь понятно почему)
2. Используй статическую линкову

Лично я пока пошёл по 2-му пути. Эта тема тут уже не однократно разжовывалась...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение MuHbKa » 22.08.2008 15:28:42

alexs писал(а):1. Используй DLL - но это черевато тем, что dll будут очень большими (надеюсь понятно почему)

Не совсем понятно, ибо с DLL приходилось иметь дело только в качестве UDF.
Все компоненты будут садится в каждый экземпляр DLL?
Аватара пользователя
MuHbKa
незнакомец
 
Сообщения: 4
Зарегистрирован: 22.08.2008 13:08:57
Откуда: Тольятти

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение alexs » 22.08.2008 16:55:26

RTL+FCL будут свои в каждой dll
в делфине таже проблема для dll, именно поэтому и придумали в борланде bpl
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение Vadim » 22.08.2008 17:22:30

MuHbKa писал(а):Все компоненты будут садится в каждый экземпляр DLL?

А это зависит от Вас, как от разработчика. :)
Можно всё в одном, а можно и разбить по нескольким. Т.е. каждая отдельная связанная друг с другом группа компонентов (например, отдельная форма и расположенные на ней же компоненты) будет лежать в своей собственной DLL.
Другое дело что DLL действительно не совсем удобна для хранения паскалевских классов Например, самой DLL (точнее общению программы на Паскале с DLL'кой) предпочтительней, чтобы строки были в виде PChar, а Вам, как разработчику - в виде AnsiString, что потребует ввести доп. модуль.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение MuHbKa » 22.08.2008 17:33:45

Можно всё в одном, а можно и разбить по нескольким. Т.е. каждая отдельная связанная друг с другом группа компонентов (например, отдельная форма и расположенные на ней же компоненты) будет лежать в своей собственной DLL.

Помоему мы говорим об одном и том же.
Т.е. Есть Form1 на которой лежит TPanel и все это собрано в Lib1.dll и Form2 котороя так же содержит TPanel и собрана в Lib2.dll
Обе DLL содержат по экзепляру TPanel и всей иерхии наследования. Нет?

Ну тогда и еще вопрос. Я так понял что интерфейс MDI на Lazarus реализовать не удастся?
Об имитации, типа компонеты MultiDoc от Patrick Chevalley не говорю. На мой взгляд выглядит это чудовищно, хотя на вкус и цвет.
Аватара пользователя
MuHbKa
незнакомец
 
Сообщения: 4
Зарегистрирован: 22.08.2008 13:08:57
Откуда: Тольятти

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение Vadim » 22.08.2008 17:51:17

MuHbKa писал(а):Обе DLL содержат по экзепляру TPanel и всей иерхии наследования.

Ну, в общем то да. Ведь у них же, у каждой формы, своя Panel? А вот если формы должны быть одинаковы, то класс формы можно держать в одной DLL, а уж сами формы плодить как тараканов от этого класса. :)
MuHbKa писал(а):Я так понял что интерфейс MDI на Lazarus реализовать не удастся?

Если честно, мне больше SDI нравится. :)
А что, FormStyle:= fsMDIForm | fsMDIChild там разве не работают? А то я как-то даже и не проверял до сих пор...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение MuHbKa » 22.08.2008 20:59:26

А вот если формы должны быть одинаковы

Не одинаковы, там от 1 до 3 уровней наследования. Как сказал alexs проще будет все влинковать в exe-шник.
А что, FormStyle:= fsMDIForm | fsMDIChild там разве не работают?

Свойства то есть, но изменение их значения к ожидаемому результату не приводит. По форуму пошарился, говорят вообще никак.
Аватара пользователя
MuHbKa
незнакомец
 
Сообщения: 4
Зарегистрирован: 22.08.2008 13:08:57
Откуда: Тольятти

Re: Аналоги LoadPackage() и UnloadPackage()

Сообщение alexs » 23.08.2008 23:34:21

MuHbKa писал(а): Я так понял что интерфейс MDI на Lazarus реализовать не удастся?

Компили под QT - там вроде это уже работает.
А насчёт
MuHbKa писал(а):Т.е. Есть Form1 на которой лежит TPanel и все это собрано в Lib1.dll и Form2 котороя так же содержит TPanel и собрана в Lib2.dllОбе DLL содержат по экзепляру TPanel и всей иерхии наследования.

В DLL-ях будет полностью RTL/FCL/LCL дублироваться. И это не есть хорошо. И взаимодествие прозрачное визуальных компонент между разными DLL нормально не работает (без всяких хаков).
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: MailRu[bot] и гости: 0

Рейтинг@Mail.ru