Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вызов в dll формы главной программы, Написание плагинов 
:(
    Опции темы
Akella
  Дата 13.3.2007, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Есть программа, которая при загрузке выполняет поиск и загрузку DLL.

При загруке Dll добавляет пункт меню и вешает обработчик. Т.е. можно как-то вызвать средствами dll какую-либо форму главной программы или какую-либо процедуру/функцию главной программы. Вопрос в том, как?

Вот этот код выполняет загрузку DLL
Код

procedure TfmMain.LoadPlugins;
Var
 h,i:integer;
  PlugExec        : procedure(sender :TObject) of object;
  PlugType        : function : integer;  //Объявление функции, которая будет возвращать тип плугина
  GetConnectInfo  : procedure(fbclient,DB:PChar);
  GetUserData     : procedure(UID:integer;UserName:PChar);
  //GetKvxHandle : procedure(g:integer);
  MenuCaption : function : PChar;
  act: TAction;
begin
  slPlagins        := TStringList.Create;
  slPlaginsHandles := TStringList.Create;
  FindPlugins(IncludeTrailingPathDelimiter(sAppPath)+'Plugins\');
  if slPlagins.Count <= 0 then begin
    FreeAndNil(slPlagins);
    exit;
  end;
  //если найдены плагины, то пытаемся их загрузить
  for I := 0 to slPlagins.Count - 1 do begin
    h := LoadLibrary(PChar(slPlagins[i]));
    if h <> 0 then begin
      @plugExec := GetProcAddress(h,'PluginExec');
      @plugType := GetProcAddress(h,'PluginType');
      @GetConnectInfo := GetProcAddress(h,'GetConnectInfo');
      @GetUserData    := GetProcAddress(h,'GetUserData');

      GetUserData(UserData.UserID,PChar(UserData.UserName));
      GetConnectInfo(PChar(DM.fibDB.LibraryName),PChar(DM.fibDB.DBName));
      with am1.ActionBars[0].Items[PlugType].Items.Add do begin
        @MenuCaption := GetProcAddress(h,'MenuCaption');
        act := TAction.Create(am1);
        act.ActionList := am1;
        act.onExecute := plugExec;
        Action := act;
        Caption := MenuCaption;
      end;//with
    end;

    //FreeLibrary(h);
  end;//for
end;


Код DLL

Код

function MenuCaption:Pchar;
begin
  result := 'Быстрый поиск - Средний этаж';
end;

function PluginType:integer;
begin
  result := 2;
end;


procedure PluginExec(Sender:Tobject);
begin
  //обработчик события при выборе меню

end;


exports
  PluginType, MenuCaption, PluginExec;

PM MAIL   Вверх
skyboy
Дата 13.3.2007, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 2
Всего: 260



Akella, никак. забей. много проблем - и ничего толком. чтоб изменить пункт меню формы, надо в интерфейсе ДЛЛ при проектировании заложить функцию, и при вызове в неё передавать указать на объект типа TForm. И функция добавить пункт меню. Но! Это вызывает две проблемы:
1. проблема размера: чтоб знать про существование класса TForm каждая DLL должна нести в своем бинарном коде описание структуры класса. Сколько плагинов - на столько раз * размер класса TFrom будет увеличено занимаемое дисковое пространство и память.
2. проблема адреса. Тут была проблемная тема на форуме: человек передавал в DLL объект класса TImage. DLL принимала. А TImage - это вообще контейнер-оболочка, сама картинка хранится в свойстве Picture. Так вот, класс этого свойства TPicture в адресном пространстве приложения и Dll отличались, т.е. считались разными. И dll по получению объекта TImage со спокойной совестью "сносила" объект Picture некорректного класса и создавала его заново. Прикольно? Картинка пришла - и очистилась smile))))
Выяснили причину такого поведения после нескольких десятков сообщений smile 
Ну,как, напугал?  smile 
Выход есть. Называется он - bpl. Т.е. пакетная библиотека smile
Найду пример использования, скину. smile

Добавлено @ 16:10 
1. вот кратенько про DLL vs BPL и пример реализации простых плагинов на пакетах.
2.  вот намного более углубленное сравнение, но и примеры - слишком замысловатые.
PM MAIL   Вверх
skyboy
Дата 13.3.2007, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 2
Всего: 260



вот тут шел спор о том, что и как реализовано в механизме dll:
 Проблемма с переменными в DLL.
А здесь Alexis сказал про разные классы, что с экспортом/импортом объектов в/из dll будет сплошь головная боль. 
Цитата(skyboy @  13.3.2007,  15:02 Найти цитируемый пост)
Тут была проблемная тема на форуме: человек передавал в DLL объект класса TImage.

А вот и сама тема: Приложене и DLL особенности их взаимодействия, Неверно функционируют компоненты . Правда, я попутал: Alexis в перевом же посте указал не только на проблему, но и на причину. smile
PM MAIL   Вверх
Snowy
Дата 13.3.2007, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



1 вариант: создать в приложении какой-то менеджер, который будет принимать сообщения и выполнять их как комманды.
2 вариант: работать через интерфейсы.
Примеров не дам - на работе завал  smile 
PM MAIL   Вверх
Alexeis
Дата 13.3.2007, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 16
Всего: 459



Akella, можно в приложении написать набор из нескольких функций, которые будут производить все необходимые операции, а при загрузке плагина передать их адреса в Dll. Т.о. все будет производиться на стороне приложения.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
MetalFan
Дата 13.3.2007, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Цитата(Snowy @  13.3.2007,  16:44 Найти цитируемый пост)
2 вариант: работать через интерфейсы.

неплохая статья с примерами:
http://delphiworld.narod.ru/base/about_com.html
и еще одна:
http://delphiworld.narod.ru/base/delphi_com.html

Это сообщение отредактировал(а) MetalFan - 13.3.2007, 17:35


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Akella
Дата 13.3.2007, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(skyboy @  13.3.2007,  16:02 Найти цитируемый пост)
чтоб изменить пункт меню формы,

с эти нет проблем, это уже раелизовано

Добавлено @ 17:45 
Цитата(skyboy @  13.3.2007,  16:02 Найти цитируемый пост)
Ну,как, напугал?

нед!  smile

Добавлено @ 17:47 
Цитата(Alexeis @  13.3.2007,  17:10 Найти цитируемый пост)
Т.о. все будет производиться на стороне приложения. 

если посмотреть на код, то так всё и сделано:

Код

PlugExec        : procedure(sender :TObject) of object;

...
with am1.ActionBars[0].Items[PlugType].Items.Add do begin
        @MenuCaption := GetProcAddress(h,'MenuCaption');
        act := TAction.Create(am1);
        act.ActionList := am1;

////////////// вот оно
        act.onExecute := plugExec;

        Action := act;
        Caption := MenuCaption;
      end;//with


или я ошибся?
PM MAIL   Вверх
Akella
Дата 13.3.2007, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Народ, мне фактически нужно следующее
из приложения (средствами DLL) вызвать функцию этого- же приложения. Допустим Что функция вызывает какую-то форму.
Вот. Я вызываю косвенно форму, а из DLL уже манипулирую этой формой.
PM MAIL   Вверх
Alexeis
Дата 13.3.2007, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 16
Всего: 459



Akella, вроде не то. Приложение должно вызвать определенную функцию из Dll и передать ей (Dll), адреса своих функций (которые и будут производить все опрации с объектами приложения). В Dll нужно создать глобальные переменные куда можно будет записать эти адреса. Теперь при вызове функции расположенной в Dll, сама Dllка сможет вызвать калбэком функции расположенные в приложении, потому что только они могут безопасно обращаться с объектами приложения. Думаю интерфесы примерно так и работают. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Akella
Дата 13.3.2007, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Цитата(Alexeis @  13.3.2007,  18:09 Найти цитируемый пост)
Приложение должно вызвать определенную функцию из Dll 

так и есть!!

Код

  act.onExecute := plugExec;

вот же, на менюху вешаю код, который "прописан" в DLL-ке.


plugExec вызывается из DLL. Вот в DLL что-то нужно написать, что бы при выполнеии
кода act.onExecute := plugExec;

выполнялась процедура из главного приложения

приложение -> act.onExecute := plugExec -> в DLL PlugExec -> вызов какой либо процедуры главного окна приложения

Добавлено @ 18:15 
Цитата(Alexeis @  13.3.2007,  18:09 Найти цитируемый пост)
В Dll нужно создать глобальные переменные куда можно будет записать эти адреса. Теперь при вызове функции расположенной в Dll, сама Dllка сможет вызвать калбэком функции расположенные в приложении,

не затруднит Вас набросать несколько строк кода, исходя из моего примера, описанного в самом верху странички  smile   smile

Добавлено @ 18:26 
распечатал инфу со сцилок, дома почитаю, я пока разбираюсь в сути, как лучше реализовать поддержку плагинов в приложении, по идее приложении и не должно знать не про какие плагины, а тупо подгружать DLL-ки. С DLL никогда не работал. А всякие примеры с этими калькуляторами(как будто ничего другого нельзя придумать), которые описаны во всех книгах и так понятны.

PM MAIL   Вверх
Alexeis
Дата 13.3.2007, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 16
Всего: 459



Вот примерно так
Это будет код программы
Код

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
//работают с объектами проги в проге, но вызовуться из библы
  PCharProc  = function (s : PChar) : boolean; stdcall;
  TColorProc = function (c : TColor) : boolean; stdcall;

//процедуры библы
  TSetClbk  = Procedure (capset : PCharProc; colorset : TColorProc); stdcall;
  Tproc     = Procedure (); StdCall;

//Эти функции будут вызываться калбэком из Dll
function SetFormCaption(s : PChar) : boolean; stdcall;
begin
  Form1.Caption := s;
  Result := true;
end;

function SetFormColor(c : TColor) : boolean; stdcall;
begin
  Form1.Color := c;
  Result := true;
end;

//Обработчик кнопки
procedure TForm1.btn1Click(Sender: TObject);
var
  hdll     : HMODULE;
  SetClbks : TSetClbk;
  Someproc : Tproc;

begin
  hdll     := LoadLibrary('SomeDll.dll');
  SetClbks := GetProcAddress(hdll, 'SetCallBacks');
  Someproc := GetProcAddress(hdll, 'ModifyForm');

  SetClbks(SetFormCaption, SetFormColor); //Передаем библе адреса калбэков

  Someproc(); //Вызваем функцию библы, которая вызовет из тела библиотеки
              //SetFormCaption и SetFormColor
  freeLibrary(hdll);
end;

end.


А у дллки такой 
Код

library SomeDll;

uses
  SysUtils,
  Graphics;

type
  PCharProc  = function (s : PChar) : boolean; stdcall;
  TColorProc = function (c : TColor) : boolean; stdcall;

var
  SetMainFormBKColor : TColorProc;
  SetMainFormCaption : PCharProc;

Procedure SetCallBacks(capset : PCharProc; colorset : TColorProc); stdcall;
Begin
  SetMainFormBKColor := colorset;
  SetMainFormCaption := capset;
end;

Procedure ModifyForm();  stdcall;
Begin
  SetMainFormBKColor(clRed);
  SetMainFormCaption('blablabla');
end;

exports ModifyForm name 'ModifyForm', SetCallBacks name 'SetCallBacks';

begin

end.




--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
MetalFan
Дата 13.3.2007, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Alexeis, а зачем огород городить, если уже все это гораздо удобнее с пом.COM реализуется? ;)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Akella
Дата 14.3.2007, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



меня ком не устраивает
PM MAIL   Вверх
Akella
Дата 14.3.2007, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



хотя, если чесно, то нужно подумать
PM MAIL   Вверх
MetalFan
Дата 14.3.2007, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Akella, я тож так думал, что ком ненужная надстройка... 
но потом когда в итоге получилось то же, но в 10 раз замудреннее... вернулся на ком-интерфейсы. код стал гораздо прозрачнее


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0732 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.