Приложение разбитое на dll

krivetko-man

Member
Joined
Nov 22, 2008
Messages
53
Reaction score
62
У меня есть довольно сложная программа, в которой четко выделяются несколько функциональных блоков. В первый раз в жизни решил разбить программу на библиотеки и заодно улучшить все блоки (переписать заново).

Поделитесь пожалуйста методикой реализации данной идеи!:) какие плюсы и минусы меня жрут? Как обеспечить взаимодействие? Как обеспечить совместимость? Как лучше грузить модули? - статически или динамически?

Спасибо.
 

Weasel

New member
Joined
May 21, 2009
Messages
2
Reaction score
0
Age
48
Если грамотно разделить то минусов наверное не будет.
А если в нескольких dll будет использоваться графический интерфейс делфи то наверное будет минус в том что каждая dll будет содержать в себе библиотеку VCL и соотвественно иметь огромные размеры исполняемых файлов. - Можно их отделить и распространять vcl с прогой.
Если загружать dll статически то тормозить будет при запуске приложения, динамически - будет подтормаживать при первом запуске функции из dll.
 

Zevs

Member
Joined
Oct 2, 2005
Messages
220
Reaction score
77
Age
21
А если в нескольких dll будет использоваться графический интерфейс делфи то наверное будет минус в том что каждая dll будет содержать в себе библиотеку VCL и соотвественно иметь огромные размеры исполняемых файлов.
VCL работает по тому же принципу, что и dll. Весь код VCL находится в библиотеках, подгружаемых при запуске программы (dll со статикой). Сама прога получается небольшой (ну, конечно от объема выполняемых прогой действий).
 

gorenski

Member
Joined
Sep 14, 2007
Messages
27
Reaction score
30
Как обеспечить взаимодействие?
Функции, вызываемые из DLL, принимают параметры и возвращают различные значение в основное приложение.
 

trolojik

Member
Joined
Jul 7, 2010
Messages
15
Reaction score
0
Age
42
Я могу загрузить свой проект динамично. статическая нагрузка может вызвать проблемы с памятью.
 

Irrezistable

Member
Joined
Apr 3, 2010
Messages
21
Reaction score
138
Вообще, для сложных проектов как раз и рекомендуется разбитие на модули...

Получится некое подобие runtime-компонентов, распространяемых с программой. Ничего сложного тут нет, все комплексные юниты записать в dll. В основном приложении осуществлять обработку значений функций. Dll грузить лучше все сразу, чтобы только при первом запуске были тормоза, потом всё будет работать плавно... юзвери ведь не любят, когда при нажатии на кнопку вдруг система залагает (будет грузить dll для обращения к какому-либо куску кода)...

Dll-файлы можно прикрепить к exe-файлу (создать 1 общий файл), с помощью пакера, например, от BoxedApp. Тогда загрузка программы будет происходить немного быстрее, а сами библиотеки можно подгружать по мере надобности, чтобы не есть лишней памяти (их копии уже будут в памяти в виде виртуальных файлов). От этого быстродействие модулей не снизится. Хотя сам пробовал всего лишь с парочкой мелких dll (функции игрового движка), возможно с крупными файлами дела обстоят хуже.
 

heath

Member
Joined
Jan 12, 2010
Messages
6
Reaction score
0
Плюсы - модульность приложения делает его структуру яснее и для авторов и для тех, кто будет это приложение поддерживать далее. При внесении изменений в код модуля, как правило не требуется перекомпиляция всего приложения, а только данного модуля.
Минус, а вернее сложность, если в модулях (dll) будет графический интерфейс, особенно, если применяются сложные компоненты (DevExpress и т.п.). Будут ошибки при работе с памятью при запуске и завершении работы приложения. Но это все исправляется, просто нужно будет время.
По поводу размеров dll при использовании vcl - сейчас уже не то время когда были сильные ограничения на объем ОЗУ и жестких дисков. Одним мегабайтом больше или меньше - это не принципиально.
Если функции в dll будут постоянно использоваться во время работы приложения, используйте статическую загрузку, если один/два раза или вообще могут быть не задействованы во время работы - используйте динамическую загрузку.
 

alex_133

New member
Joined
Jul 5, 2006
Messages
4
Reaction score
0
Location
Россия
Самое главное о чем стоит помнить при использовании длл - общий memory manager (если передаете данные по указателям на обьекты)
 

heath

Member
Joined
Jan 12, 2010
Messages
6
Reaction score
0
ShareMem нужно использовать если будут передаваться длинные строки или объекты их содержащие. Без ShareMem можно обойтись, если передавать строки как PChar.
 

demav

Member
Joined
Nov 20, 2018
Messages
301
Reaction score
53
Age
39
krivetko-man, напишите пожалуйста - удалось ли разделить приложение на DLL?

Я в своё время тоже пытался это сделать, но возникло много проблем. Начиная от хэндлов окон (их надо передавать для MDI приложения) и единого стиля в DevExpress, до логических. Не буду подробно описывать все проблемы, но в итоге все вернул в единое приложение.
ShareMem, кстати, не надо использовать начиная с BDS 2006.
 

heath

Member
Joined
Jan 12, 2010
Messages
6
Reaction score
0
ShareMem скорее всего уже подключается автоматически.

Добавлено через 1 минуту
krivetko-man, напишите пожалуйста - удалось ли разделить приложение на DLL?

Я в своё время тоже пытался это сделать, но возникло много проблем. Начиная от хэндлов окон (их надо передавать для MDI приложения) и единого стиля в DevExpress, до логических. Не буду подробно описывать все проблемы, но в итоге все вернул в единое приложение.
ShareMem, кстати, не надо использовать начиная с BDS 2006.

Напиши некоторые проблемы. Попробуем решить. Я с этим много раз сталкивался.
 
Last edited by a moderator:

dimamir

Member
Joined
Jul 28, 2006
Messages
9
Reaction score
3
Location
СПб
Разделять на кучу dll имеет смысл только при крайней необходимости.
Проблем с памятью не избежать. Отладки будет не меряно... А сколько потом вылезет при эксплуатации - ужас
Лучше потратить время с пользой - просто переписать прогу и не лезть в дебри...
Как уже писали проблем с объемом памяти сейчас нет. Тем более если загружать статически. DLL обычно используют когда работает большая группа разработчиков и детально прописан интерфейс между модулями.
 

Alexonix

Member
Joined
Nov 18, 2010
Messages
5
Reaction score
0
Я в свое время когда изучал этот вопрос и был сильно разачарован что в Дельфи нет хорошего способа для разделения программы на модули (типа plugins). А разделение на DLL очень не рекомендую, если вы используете какие-либо библиотеки (графика, формы и т.д.). Будет, например, проблема что TForm <> TForm из DLL. :)
 

spasius

Member
Joined
Apr 8, 2009
Messages
5
Reaction score
0
есть альтернативы. BPL или скриптовой движок, при этом тексты скриптов можно хранить и в DLL, получится компромисс.
 

sunzh

Member
Joined
Jan 13, 2011
Messages
10
Reaction score
0
В VisualStudio есть поддержка ресурс-DLL, в том числе и ресурсов окон диалога.

В Delphi это тоже возможно, но все кодируется вручную.

Если речь идет о динамической загрузке библиотек, то разбивка исходного кода на модули - задача не столь очевидная. Придется определить, какие именно части кода и ресурсы возможно перенести в Dll, придется реализовать вызовы, загрузку и освобождение памяти. Это приведет к существенному изменению и усложнению логики приложения. Да и уровень программирования в этом случае пониже, широко используется Win API, так что Microsoft SDK Help вам в помощь. : )
 
Last edited by a moderator:

sunzh

Member
Joined
Jan 13, 2011
Messages
10
Reaction score
0
Пример динамической загрузки диалогов:

Вызов:

Code:
procedure TForm1.Button11Click(Sender: TObject);
var
  ExecDialog:TExecDialog;
  HLib:THandle;
  P:pchar;
  S:string;
begin
  HLib:=0;
  try
    HLib:=LoadLibrary('FirstLib.dll');
    if HLib>0 then begin
      ExecDialog:=GetProcAddress(HLib,'ExecDialog');
      if Assigned(ExecDialog) then begin
        if ExecDialog(Application.Handle,P) then begin
          S:=P;
          Caption:=S;
        end;
      end else ShowMessage('Method with name ExecuteDialog was not found');
    end else ShowMessage('Can not load library FirstLib.dll');
  finally
    Application.ProcessMessages;
    if HLib>0 then FreeLibrary(HLib);
  end;
end;

Функция в DLL:

Code:
function ExecDialog(AppHandle:THandle; var PictName:pchar):boolean; stdcall; export;
var
  FDialog:TForm1;
begin
  FDialog:=nil;
  PictName:=nil;
  Result:=False;
  Application.Handle:=AppHandle; {Two icons are arisen at taskbar without this operator. Warning while dynamic loading!}
  try
    FDialog:=TForm1.Create(Application);
    if FDialog.ShowModal=mrOK then begin
      FillMemory(@C[0],1000,0);
      if length(FDialog.Edit1.Text)>0 then StrPCopy(C,FDialog.Edit1.Text);
      PictName:=@C[0];
      Result:=True;
    end;
    FDialog.Release;
    FDialog:=nil;
    {!!! Case dynamic loading, one has to use method Free instead of Release!}
  except
    On E:exception do begin
      ShowMessage(E.Message);
      if Assigned(FDialog) then FDialog.Release;
    end;
  end;
  Application.ProcessMessages;
  Application.Handle:=0;
end;
 

prodigy

New member
Joined
Feb 15, 2010
Messages
1
Reaction score
0
Age
31
Работы будет море - это однозначно, но в случае сложного проекта усилия будут не напрасны. Удачное разделение на dll-ки упростит общую схему проекта, обновление и поддержку, а также позволит избежать множества трудноотловимых глюков многомодульного приложения.
Несколько советов:
1) Чтобы избежать дублирования кода в отдельных библиотеках, проблем с графическим интерфейсом и такими компонентами, как DevExpress, надо обязательно использовать пакеты времени исполнения. Минус - вместе с программой надо распространять все используемые bpl. Плюсы - малый размер библиотек и исполняемых файлов, отсутствие глюков с компонентами и графикой, связанными с дублированием кода в каждом модуле.
2) Строковые параметры необходимо передавать только указателями типа PChar (или PAnsiChar, PWideChar).
3) Есть определенная грань сложности проекта и интерфейсов взаимодействия составляющих его бибилиотек, пересекая которую лучше обратить свой взор в сторону такой технологии, как COM. Она способна значительно упростить жизнь разработчику, взяв на себя часть работы по обеспечению взаимодействия, обратных вызовов и прочих достаточно сложных ньюансов при разработке сложных приложений.
 

maremora

Member
Joined
Oct 10, 2009
Messages
10
Reaction score
0
реально симпатичное решение предложено и почти целиком описано у Gansmoker-a в блоге
Жаль, что не озвучена авторская идея серверной части для вкладывания форм в плагины ... с пониманием полной идеи было бы проще...
 

ColdS

Premium
Joined
May 26, 2008
Messages
6
Reaction score
3
Я частенько сую в dll отдельные куски программы - от общих функций до окон и фреймов. Очень удобно, если конечному пользователю поставляешь не "проф" версию, а отдельный набор функциональности. Да и поддерживать проще...
В качестве взаимодействия можно использовать результаты функций, конечно. У меня мои dll (с формами, фреймами) общаются между собой сообщениями. В основной программе обработчик. Это дает какую-то модульность.
 

vovag3074

Member
Joined
Jan 15, 2010
Messages
44
Reaction score
74
Age
48
2) Строковые параметры необходимо передавать только указателями типа PChar (или PAnsiChar, PWideChar).
Можно передавать и WideString - это системные вызовы. для разбивки лучше использовать функциональные модули. У меня в проекте в 5-и местах идет редактирование внешних контактов. Вызываю из DLL. В другом случае: использую технологию COM и динамическую загрузку. Можно пойти дальше .NET - технология, это дальнейшее развитие СОМ технологии. Но начиная с определенного размера - резать все равно придется. Посмотрите на фирменные программы - сколько там библиотек! А когда идет подгрузка можно вывести панельку с часиками - вот уже и нет тормозов.
 
Top