Конференция "Corba" » Подключение плагинов ДМ [Delphi, Windows]
 
  • rus_999 (21.01.09 13:00) [0]
    У меня такая проблема, нужно подключить и использовать плагины Download Master'а в своей программе. Мало с этой технологией сталкивался и никак не получается.

    Объявления интерфейсов
    unit DMPluginIntf;

    //описание см. в readme.txt

    interface

    type
     { IDMInterface }
     IDMInterface = interface(IUnknown)
     ['{B412B405-0578-4B99-BB06-368CDA0B2F8C}']
       function DoAction(action: WideString; parameters: WideString): WideString; stdcall;//выполнить какие-либо действия в ДМ
     end;

     { IDMPlugIn }
     IDMPlugIn = interface(IUnknown)
     ['{959CD0D3-83FD-40F7-A75A-E5C6500B58DF}']
       function getID: WideString; stdcall;
       //-----info
       function GetName: WideString; stdcall;//получаем инфу о плагине
       function GetVersion: WideString; stdcall;//получаем инфу о плагине
       function GetDescription(language: WideString): WideString; stdcall;//получаем инфу о плагине
       function GetEmail: WideString; stdcall;//получаем инфу о плагине
       function GetHomepage: WideString; stdcall;//получаем инфу о плагине
       function GetCopyright: WideString; stdcall;//получаем инфу о плагине
       function GetMinAppVersion: WideString; stdcall;//получаем минимальную версию ДМ-а с которой может работать плагин

       //------
       procedure PluginInit(_IDmInterface: IDmInterface); stdcall;//инициализация плагина и передача интерфейса для доступа к ДМ
       procedure PluginConfigure(params: WideString); stdcall;//вызов окна конфигурации плагина
       procedure BeforeUnload; stdcall;

       function EventRaised(eventType: WideString; eventData: WideString): WideString; stdcall;//вызывается из ДМ-ма при возникновении какого либо события
       { идентификатор плагина }
       property ID: WideString read getID;
     end;

    implementation

    end.



    Реализация тестового плагина

    interface

    uses DMPluginIntf, Classes, Dialogs;
    const
     //укажите здесь информацию о своем плагине
     myPluginID = '{45145BBE-DCAE-4187-B981-FE9410F6DA5D}';//обязательно укажите свой уникальный номер плагина (используйте Ctrl+Shift+G для генерации)
     myPluginName = 'Download Master Test Plug-in';//название плагина на английском языке
     myPluginVersion = '0.1.1.1';
     myPluginEmail = 'slava@westbyte.com';
     myPluginHomePage = 'http://www.westbyte.com/dm/';
     myPluginCopyRight = chr(169)+'2006 WestByte';
     myMinNeedAppVersion = '5.0.2';//версия указывается без билда
     //описание плагина. Должно быть представлено на русском и английском языках. Может содержать подробную инструкцию по пользованию плагином.
     myPluginDescription = 'Test Plug-in for show how create plugins for DM';
     myPluginDescriptionRussian = 'Тестовый плагин для демонстрации как создавать плагины для DM. Является одновременно шаблоном для создания плагинов. Язык реализации Delphi 7.';
     
    type
    TDMTestPlugIn = class(TInterfacedObject, IDMPlugIn)
     private
       myIDmInterface: IDmInterface;
     protected

     public
       function getID: WideString; stdcall;
       //-----info
       function GetName: WideString; stdcall;//получаем инфу о плагине
       function GetVersion: WideString; stdcall;//получаем инфу о плагине
       function GetDescription(language: WideString): WideString; stdcall;//получаем инфу о плагине
       function GetEmail: WideString; stdcall;//получаем инфу о плагине
       function GetHomepage: WideString; stdcall;//получаем инфу о плагине
       function GetCopyright: WideString; stdcall;//получаем инфу о плагине
       function GetMinAppVersion: WideString; stdcall;//получаем минимальную версию ДМ-а с которой может работать плагин

       //------
       procedure PluginInit(_IDmInterface: IDmInterface); stdcall;//инициализация плагина и передача интерфейса для доступа к ДМ
       procedure PluginConfigure(params: WideString); stdcall;//вызов окна конфигурации плагина (окно конфигурации реализуется вами самостоятельно)
       procedure BeforeUnload; stdcall;//вызывается перед удалением плагина

       function EventRaised(eventType: WideString; eventData: WideString): WideString; stdcall;//вызывается из ДМ-ма при возникновении какого либо события
       { идентификатор плагина }
       property ID: WideString read getID;

     published

    end;

    implementation

    Дальше реализация функций



    Помогите плиз, пробовал так, но не выходит!

    var
    handle : thandle;
    PlugIn : function : IDMPlugin;
    plug : IDMPlugin;
    intf : IDMInterface;
    label ex;
    begin
    handle:=loadlibrary(pchar(extractfilepath(paramstr(0))+'Dll\dmtest_plugin.dll'));
    PlugIn:=getprocaddress(handle,'RegisterPlugIn');
    plug:=plugin;
    plug.GetName;
    //plugin.PluginInit(intf);
    ex:
    freelibrary(handle);
    end;

  • tesseract © (21.01.09 14:35) [1]
    А что не выходит то ? Нао печатывался где не попадя вот и не выходит. Читай внимательнее : http://www.interface.ru/fset.asp?Url=/borland/decom_1.htm
  • rus_999 (21.01.09 15:00) [2]
    При вызове функции getname вылетает с ошибкой.
  • rus_999 (21.01.09 15:03) [3]
    Подправьте код, большого не прощу! Пока во всем этом разберешься.
  • tesseract © (21.01.09 15:18) [4]

    > При вызове функции getname вылетает с ошибкой.


    Это я вижу поверь это не одна ошибка. Ты зачем plugin function IDMPlugin обозвал? Он TDMTestPlugin должен быть.

    И код plug:=plugin.RegisterPlugin где? В статье всё это великолепно расписано, время на чтение не больше 30 минут.
  • rus_999 (21.01.09 15:57) [5]
    Смысл обращаться за помощью, если тебя читать отправляют вместо решения?! Сама длл определенного формата, я его не задаю, там нет функции plugin.RegisterPlugin.
  • tesseract © (21.01.09 16:09) [6]

    > Сама длл определенного формата, я его не задаю, там нет
    > функции plugin.RegisterPlugin.


    В dpr файле она есть, я в примере специально посмотрел. Там всё как описано в данной статье, там твой пример детально на второй странице разжёван.


    > Смысл обращаться за помощью, если тебя читать отправляют
    > вместо решения?!

    Хоть поймёшь что делаешь. Если хочешь полное решение - это уже коммерческое предложение.
  • rus_999 (21.01.09 16:12) [7]
    Спс, попробую все снова.
  • Korney San © (26.02.09 17:59) [8]
    Усложним задачу.
    Я сделал "расширитель" интерфейса - унаследовал

    IDMThunkInterface = interface(IDMInterface)
    end;

    TDMThunkInterface = class(TInterfacedObject, IDMThunkInterface)
     function DoAction(action: WideString; parameters: WideString): WideString; stdcall;
     constructor Create(_IDMInterface: IDMInterface; Plugins: PPlgInstances; ConfigForm: PThunkSetupForm);
     procedure Free; stdcall;
    private
     thunkIDMInterface: IDMInterface;
     AllPlugins: PPlgInstances;
     AForm: PThunkSetupForm;
     ...
    end;


    с целью подключать к СВОЕМУ плагину ДРУГИЕ плагины DM и фильтровать их "обмен" с DM, а также получить возможность межплагинного обмена данными.
    Ввёл несколько нужных типов:

    type

    TRegisterPlugIn = function: IDMPlugIn; stdcall;

    TPlgInstance = Record
    Handle: THandle;
    PlgRegister: TRegisterPlugIn;
    PlgIntf: IDMPlugIn;
    PlgID: WideString;
    FileName: String;
    end;

    TPlgInstances = array of TPlgInstance;
    PPlgInstances = ^TPlgInstances;


    В своём "стандартном" плагине я делаю так:

    procedure TDMTestPlugIn.PluginInit(_IDmInterface: IDmInterface);//инициализация плагина и передача интерфейса для доступа к ДМ
    begin
     myIDmInterface := _IDmInterface;
     ...
     SetLength(Plugins, 0);
     ...
     myThunk:=nil;
     myThunk:=TDMThunkInterface.Create(_IDmInterface, Addr(Plugins), Addr(CF));
     //
     FindPlugins;
    end;


    FindPlugins заполняет массив именами найденных плагинов, которые подключаются и отключаются так:

    function TDMTestPlugIn.ConnPlg(Idx: Integer): Integer;
    begin
    if (Idx>=Low(Plugins)) and (Idx<=High(Plugins)) then
     begin
      Result:=cnxOK;
      if FileExists(Plugins[Idx].FileName) then
       begin
        Plugins[Idx].Handle:=LoadLibrary(PChar(Plugins[Idx].FileName));
        if Plugins[Idx].Handle = 0 then
          Result:=cnxLoadFailed
        else
         begin
          Plugins[Idx].PlgRegister:=nil;
          @Plugins[Idx].PlgRegister := GetProcAddress(Plugins[Idx].Handle, 'RegisterPlugIn');
          if Assigned(Plugins[Idx].PlgRegister) then
           begin
            Plugins[Idx].PlgIntf:=Plugins[Idx].PlgRegister();
            Plugins[Idx].PlgID:=Plugins[Idx].PlgIntf.ID;
            Plugins[Idx].PlgIntf.PluginInit(myThunk); //отдаю СВОЙ интерфейс
           end
          else
            Result:=cnxNoInit;
         end;
       end
      else
        Result:=cnxNotFound;
     end
    else
      Result:=-1;
    end;
    //------------------------------------------------------------------------------
    procedure TDMTestPlugIn.RemPlg(Idx: Integer);
    begin
    if (Idx>=Low(Plugins)) and (Idx<=High(Plugins)) then
     begin
      if Plugins[Idx].Handle<>0 then
       begin
        Plugins[Idx].PlgIntf.BeforeUnload; //"чищу" сам плагин
        Plugins[Idx].PlgID:='';
        Plugins[Idx].PlgIntf:=nil; //закрываю его интерфейс
        Plugins[Idx].PlgRegister:=nil; //очищаю указатель на фукнцию регистрации
        FreeLibrary(Plugins[Idx].Handle);
        Plugins[Idx].Handle:=0;
       end;
     end;
    end;


    Передача данных между подключёнными "в массив" плагинами реализована так:
    плагин-отправитель вызывает DoAction у myThunk, а myThunk определяет адресата и вызывает ему EventRaised.
    Написал два тестовых плагина - один вызывает команду другого. Отлично работают друг с другом... до той поры, пока один из них не выгрузить (сделал такую возможность) и не загрузить обратно (через RemPlg и ConnPlg соответственно).
    После этой операции плагины сами по себе работают, но друг друга "не видят".

    Уже сломал голову над поиском причины. Подскажите, пожалуйста, где я свернул не в ту сторону.
 
Конференция "Corba" » Подключение плагинов ДМ [Delphi, Windows]
Есть новые Нет новых   [134428   +41][b:0][p:0.005]