Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.05.2011, 22:57   #11
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

Интересно.

Но все-таки как реализовать обмен чем-либо мужду плагином и ядром?
Каким образом? Если сообщения не удобны.

Последний раз редактировалось Человек_Борща; 10.05.2011 в 23:00.
Человек_Борща вне форума Ответить с цитированием
Старый 10.05.2011, 23:03   #12
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Ты спросил общий вопрос - я дал общий ответ.

Хочешь услышать что-то конкретное - конкретно скажи, что тебя интересует.

Повторю ещё раз в общих словах: у ядра на руках есть интерфейсы плагинов (IHLRPlugin), а у плагина на руках есть интерфейс ядра (IHLRCore). Когда кому-то из них нужно что-то от другой стороны - они вызывают метод другой стороны.

К примеру, если плагину нужно что-то от ядра - он вызывает метод, скажем, IHLRCore.GetSomeData. GetSomeData возвращает данные, которые запросил плагин.

Если ядру что-то надо от плагина, оно вызывает метод, скажем, IHLRPlugin.GetSomeOtherUsefulData.

Я не могу тебе сказать конкретный пример, потому что ты ничего не говоришь про то, какие данные ты собрался передавать. Поэтому я могу сказать только такие общие слова.

Тут главное не забывать, что мы работаем на интерфейсах. И не умудриться при этом свалить всё в кучу.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 10.05.2011, 23:10   #13
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

т.е. то общение которое я хочу уже представлено на примере, когда IHLCore запрашивает данные у плагина ввиде:
Код:
var
s:string;
begin
s:=PluginsList.plugins[i].GetVersion; ? 
end;
Человек_Борща вне форума Ответить с цитированием
Старый 10.05.2011, 23:16   #14
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Я не знаю, чего ты хочешь - ты же не сказал.

В демке: передача данных от плагина к ядру по команде ядра выглядит так:

Код:
procedure TForm1.Button2Click(Sender: TObject);
var
  Data: String;
begin
  Data := Plugins[0].Author; // мы передали строку из плагина в ядро
end;
Наоборот, передача данных от ядра плагину по указке плагина:

Код:
  IHLRCore = interface(IUnknown)
  ['{CB707CEE-3191-47CC-B5C5-D4A936F5CACA}']
    function GetSomeData: WideString; safecall; // <- добавили. + надо его реализовать в THLRPlugins
  end;
Код:
function TTestPlugin.GetPluginName: WideString; safecall;
begin
  Result := 'Hello World for ' + FCore.GetSomeData;
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 10.05.2011, 23:21   #15
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

Вот теперь понятнее =)
Пойду разбираться...
Человек_Борща вне форума Ответить с цитированием
Старый 11.05.2011, 20:55   #16
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

Разобрался с кодом:
IHLrCore - базовый интерфейс который реализует отдачу всяческой базовой фигни(типа версии и т.д. и т.п.)
IHLRPlugin - интерфейс реализующий плагин и его способ общения с программой.
THLRPlugin - класс хранения данных об одном обьекте(1 плагин).
THLRPlugins - контейнер обьектов THLRPlugin.

Далее по поводу меню.
Я создал такой интерфейс:
Код:
  IHLRMenu = interface(IUnknown)
  ['{BFF9ED86-3C00-4613-88CB-F33B7AC0C37A}']
    procedure AddMenuItem(aName:string);
    procedure RemoveItem(aName:String);
  end;
в HLRPluginInterf.pas

Далее где мне реализовать его дальше?
Надо ли делать в THLRPlugin такую вещь:
Код:
HLRMenu:IHLRMenu;
Если да то, что делать далее?
Человек_Борща вне форума Ответить с цитированием
Старый 11.05.2011, 21:07   #17
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

IHLRMenu однозначно должна реализовывать форма, меню которой ты собрался управлять с помощью этого интерфейса:

Код:
type
  TForm1 = class(TForm, IHLRMenu)
    ...
  protected
    procedure AddMenuItem(const AName: WideString); safecall;
    procedure RemoveItem(const AName: WideString); safecall;
  end;
У THLRPlugins должно быть свойство на чтение-запись типа IHLRMenu. Ему (THLRPlugins) надо переопределить GetInterface. Там по умолчанию такой код: возвращаем себя (Self), если у нас запросили интерфейс, который мы реализуем. THLRPlugins реализует IHLrCore - вот его он и сможет вернуть. Чтобы сюда вставить IHLRMenu, меняем метод GetInterface: добавляем проверку: если запросили IHLRMenu (проверяем по GUID), то возвращаем интерфейс из свойства, о котором я в самом начале говорил.

Ну, остаётся только в FormCreate установить Self (т.е. форму) в это новое свойство менеджера плагинов.

Ну а плагин спокойно сможет использовать IHLRMenu:
Код:
var
  Menu: IHLRMenu;
begin
  if Supports(FCore, IHLRMenu, Menu) then
    Menu.AddMenuItem('Hello from plugin');
Разумеется, если ты в плагине собираешься постоянно дёргать IHLRMenu, то лучше ссылку на него сохранить в новом поле (рядом с FCore).

P.S. Не забываем про WideString и safecall. Также, рекомендую идентифицировать всё по GUID, либо вести в самой программе учёт:

Код:
    function AddMenuItem(const AName: WideString): Integer; safecall;
    procedure RemoveItem(const AID: Integer); safecall;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 11.05.2011, 22:53   #18
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

Цитата:
У THLRPlugins должно быть свойство на чтение-запись типа IHLRMenu.
А у THLRPlugin?
Код:
  THLRPlugin = class
  private
    //Обькст родитель(приемник)
    FContainer: THLRPlugins;
    //Точка входа dll плагина
    FDLLHandle: HMODULE;
    // интерфейс плагина
    FPlugin: IHLRPlugin;
    //интерфейс доступа к меню программы
    FMenu:IHLRMenu;
    // Интерфейс ссылка
    FPluginID: TGUID;
  public
    constructor Create(const AContainer: THLRPlugins; const AFileName: String);
    destructor Destroy; override;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    property Plugin: IHLRPlugin read FPlugin;
    property PluginID: TGUID read FPluginID;
    property Menu:IHLRMenu read FMenu;
  end;

Код:
 Ему (THLRPlugins) надо переопределить GetInterface. Там по умолчанию такой код: возвращаем себя (Self), если у нас запросили интерфейс, который мы реализуем. THLRPlugins реализует IHLrCore - вот его он и сможет вернуть. Чтобы сюда вставить IHLRMenu, меняем метод GetInterface: добавляем проверку: если запросили IHLRMenu (проверяем по GUID), то возвращаем интерфейс из свойства, о котором я в самом начале говорил.

 Ну, остаётся только в FormCreate установить Self (т.е. форму) в это новое свойство менеджера плагинов.
Можно эту часть более доступно описать?
Человек_Борща вне форума Ответить с цитированием
Старый 11.05.2011, 23:11   #19
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
А у THLRPlugin?
А зачем он там? Ты хочешь, каждому плагину выдать по главному меню или как?

Мне казалось, ты ввводишь IHLRMenu, чтобы плагин мог добавлять и убирать пункты в меню своей программы.

Не, для определённых хитрых целей такое сделать можно. Но в общем случае - не нужно. Один общий IHLRMenu - достаточно.

Цитата:
Можно эту часть более доступно описать?
Т.е. написать за тебя код?

Код:
type
  // Добавили свойство, чтобы его могла установить форма
  IHLRPlugins = interface
  // private
    ...
    function GetMenu: IHLRMenu; safecall;
    procedure SetMenu(const AMenu: IHLRMenu); safecall;
  // public
    ...
    property Menu: IHLRMenu read GetMenu write SetMenu;
  end;

...

  // Само свойство в менеджере
  THLRPlugins = class(TObject, IInterface, IHLRCore, IHLRPlugins)
  private
    ...
    FMenu: IHLRMenu;
  protected
    ...
    // IHLRPlugins
    ...
    function GetMenu: IHLRMenu; safecall; // методы читают/пишут FMenu - не их писать
    procedure SetMenu(const AMenu: IHLRMenu); safecall;
  public
    ...
  end;

...

function THLRPlugins.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  // Проверка на встроенные базовые вещи (IHLRCore)
  if GetInterface(IID, Obj) then
    Result := S_OK
  else
  begin
    // Проверка на сторонние расширения
    if Assigned(FMenu) and Supports(FMenu, IID, Obj) then
      Exit;
    
    // <- сюда вставляем аналогичные проверки от других вещей в твоей программе

    Result := E_NOINTERFACE;
  end;
end;
Код:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Plugins.Menu := Self; // указали плагинам использовать меню этой формы
  Plugins.LoadAll(ExtractFilePath(ParamStr(0)) + 'plugins\'); // и загрузили их

  // порядок важен
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 11.05.2011, 23:49   #20
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,434
По умолчанию

Ок, можно и так. Я видимо по прежнему далёк от этой темы,что огорчает.
Похоже я не понимаю как реализовать простую иерархию в данной системе.


Set|GetMenu реализовал вот так:
Код:
function THLRPlugins.GetMenu: IHLRMenu;
begin
  Result:=FMenu;
end;

procedure THLRPlugins.SetMenu(const aMenu: IHLRMenu);
begin
  FMenu:=aMenu;
end;

При запуске программы, осыпаемся вот с таким текстом:
Код:
exception class   : EOleException
exception message : Разрушительный сбой.

main thread ($abc):
004a01b3 +087 MainApplication.exe PluginsBaseUnit 271 +16 THLRPlugin.Create
0049fe6b +013 MainApplication.exe PluginsBaseUnit 147  +2 THLRPlugins.LoadPlugin
0049fff0 +0e4 MainApplication.exe PluginsBaseUnit 200 +11 THLRPlugins.LoadAll
004a06af +06f MainApplication.exe MainFormUnit     37  +2 TForm1.FormCreate
0049625d +031 MainApplication.exe Forms                   TCustomForm.DoCreate
00495f3d +011 MainApplication.exe Forms                   TCustomForm.AfterConstruction
00403f17 +007 MainApplication.exe System                  @AfterConstruction
00495f14 +174 MainApplication.exe Forms                   TCustomForm.Create
0049d5fd +031 MainApplication.exe Forms                   TApplication.CreateForm
004a0eab +02f MainApplication.exe MainApplication  15  +2 initialization

disassembling:
[...]
004a0179 263   test    esi, esi
004a017b       jnz     loc_4a0182
004a017d 264   call    -$48cf6 ($45748c)      ; SysUtils.RaiseLastOSError
004a0182 266   push    $4a022c                ; '07D27A370CA7409F9DC16288A592CF4F'
004a0187       mov     eax, [ebx+8]
004a018a       push    eax
004a018b       call    -$98db8 ($4073d8)      ; Windows.GetProcAddress
004a0190       mov     esi, eax
004a0192 268   test    esi, esi
004a0194       jnz     loc_4a019b
004a0196 269   call    -$48d0f ($45748c)      ; SysUtils.RaiseLastOSError
004a019b 271   lea     eax, [ebp-8]
004a019e       call    -$99a23 ($406780)      ; System.@IntfClear
004a01a3       push    eax
004a01a4       test    edi, edi
004a01a6       jz      loc_4a01ab
004a01a8       sub     edi, -$c
004a01ab       push    edi
004a01ac       call    esi
004a01ae       call    -$99923 ($406890)      ; System.@CheckAutoResult
004a01b3     > mov     edx, [ebp-8]            ; <- EXCEPTION
004a01b6       lea     eax, [ebx+$c]
004a01b9       call    -$99a26 ($406798)      ; System.@IntfCopy
004a01be 273   cmp     dword ptr [ebx+$c], 0
004a01c2       jnz     loc_4a01d0
004a01c4 276   push    $1f
004a01c6       call    -$98c3b ($407590)      ; Windows.SetLastError
004a01cb 278   call    -$48d44 ($45748c)      ; SysUtils.RaiseLastOSError
004a01d0 281   lea     eax, [ebp-$18]
004a01d3       push    eax
004a01d4       mov     eax, [ebx+$c]
004a01d7       push    eax
004a01d8       mov     eax, [eax]
004a01da       call    dword ptr [eax+$c]
004a01dd       call    -$99952 ($406890)      ; System.@CheckAutoResult
004a01e2       lea     esi, [ebp-$18]
004a01e5       lea     edi, [ebx+$10]
004a01e8       movsd
004a01e9       movsd
004a01ea       movsd
004a01eb       movsd
[...]

Последний раз редактировалось Человек_Борща; 11.05.2011 в 23:54.
Человек_Борща вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подключение интерфейсов к DLL DENISLED Помощь студентам 2 02.04.2011 21:22
Подключение интерфейсов к DLL(написаном на WinAPI) DENISLED Win Api 1 02.04.2011 19:34
Плагины через dll Lime Общие вопросы Delphi 7 17.06.2010 20:50
Переделать ввиде меню! raspberry Общие вопросы C/C++ 0 05.04.2010 23:33
микшер на два потока в проигрывателе музыки. проигрыватель сделан на основе библиотеки Bass.dll D-fens Мультимедиа в Delphi 4 08.06.2007 20:36