Jak odwołać się do interfejsu?

0

Mam definicję interfejsu:

unit intfPlugins;

// Definicja głównego interfejsu wtyczek
type
  IPlug = interface(IInterface)
    [SID_IPlug]
    function Init(ap: IPlugsApplication; TabH: HWND; ACliHandle: Pointer = nil): HResult; stdcall;
    function InitSettingsTab(TabH: HWND; out FormH: HWND): HRESULT; stdcall;
  end;

// Rozszerzenie głównego interfejsu o wtyczkę SMS
type
  IPluginSMS = interface(IPlug)
    [SID_IPlugSMS]
    procedure SendSMS(APhoneNumber, AMessage: PAnsiChar); stdcall;
    procedure SendSMS_Form(APhoneNumber, AReceiverName: PAnsiChar); stdcall;
  end;

następnie w DLL implementuję ten interfejs poprzez dziedziczenie:

unit implPluginSMS

type
  TSMSModule = class(TComObject, IPluginSMS, ISettings)
  private

  public
//IPluginSMS
    procedure SendSMS(APhoneNumber, AMessage: PAnsiChar); stdcall;
    procedure SendSMS_Form(APhoneNumber: PAnsiChar; AReceiverName: PAnsiChar); stdcall;
//ISettings
    procedure LoadSettings; stdcall;
    procedure SaveSettings; stdcall;
 public
    procedure Initialize; override;
    destructor Destroy; override;
  end;

procedure TSMSModule.SendSMS(APhoneNumber, AMessage: PAnsiChar);
begin
  // kod wyslania SMS
end;

procedure TSMSModule.SendSMS_Form(APhoneNumber, AReceiverName: PAnsiChar);
var
  SMS: TfrmSendSMS;
begin
  SMS := TfrmSendSMS.Create(Application);
  try
    SMS.Start(APhoneNumber, AReceiverName);
    SMS.ShowModal;
  finally
    SMS.Free;
    SMS := nil;
  end;
end;

Pytanie brzmi w jaki sposób odwołać się do procedury interfejsu SendSMS z poziomu okna frmSendSMS? Dodam, że procedury IPluginSMS są widoczne dla aplikacji rodzica tzn:
W aplikacji głównej wywołuję metodę IPlug.INIT a w niej, szukam pochodnej intererfejsu IPluginSMS, wówczas otrzymuję dostęp do jego implementacji.

Klasa TSMSModule jest tworzona przy inicjalizacji DLL za pomocą fabryki.

initialization
  CoInitialize(nil);
  TSMSPlugFactory.Create(ComServer, TSMSModule, CLSID_ModulSMS, '',
    'Moduł SMS', ciMultiInstance, tmApartment);
0

Pytanie brzmi w jaki sposób odwołać się do procedury interfejsu SendSMS z poziomu okna frmSendSMS?

Nie rozumiem natury problemu.

W aplikacji głównej wywołuję metodę IPlug.INIT a w niej, szukam pochodnej intererfejsu IPluginSMS, wówczas otrzymuję dostęp do jego implementacji.

Co to znaczy „szukam pochodnej intererfejsu” i „otrzymuję dostęp do jego implementacji”?
Za dużo skrótów myślowych. Nie wiadomo o co ci chodzi.

0

Dokładnie pokaż co masz w aplikacji trzeba sprawdzić czy wywołałeś CoCreateInstance (i czy sprawdziłeś co zwróciło) i w ogóle co tam narobiłeś.

0

Aplikacja główna

// Wczytanie pluginu

procedure TPluginManager.LoadPlugin(APluginName: string; APageControl: TAdvOfficePager; AForm: TForm; ACliHandle: Pointer = nil);
var
  PlugGUID: TGUID;
  HR: HResult;
  Plugin: TPlugs;
  idx: integer;
begin
  idx := FPluginList.IndexOf(APluginName);
  if idx <> -1 then
  begin
    Plugin := TPlugs(FPluginList.Objects[idx]);

    if Plugin.Loaded then
      exit;

    PlugGUID := StringToGuid(Plugin.CLSID);

    HR := CoCreateInstance(PlugGUID, nil, CLSCTX_INPROC_SERVER, IID_IPlug, Plugin.Int);
    if SUCCEEDED(HR) then
    begin


      {Plugin.TabMain := TAdvOfficePage.Create(APageControl);
      Plugin.TabMain.Parent := APageControl;
      Plugin.TabMain.Caption := Plugin.Name;
      APageControl.AddAdvPage(Plugin.TabMain);}
                                                           //Plugin.TabMain.Handle
      If SUCCEEDED(Plugin.Int.Init(AForm as IPlugsApplication, 0, ACliHandle)) then
      begin
        Plugin.Loaded := true;

        // Pobieramy interfejs do wczytywania i zapisywania ustawien
        SUCCEEDED(Plugin.Int.QueryInterface(IID_ISettings, Plugin.IntSettings));
      end
      else if Assigned(Plugin.TabMain) then
        Plugin.TabMain.Free;
    end;
  end;
end;

Wywołanie okna z wysyłaniem SMS

var
  Plugin: TPlugs;
begin
  Plugin := PluginManager.GetPluginByCLSID(TLicenseManager.Modul_SMS);

  if Plugin.Loaded then
  begin
    if Assigned(Plugin) then
    begin
      if Trim(FDOrders.FieldByName('telefon').AsString) <> '' then
        (Plugin.Int as IPluginSMS).SendSMS_Form(PAnsiChar(FDOrders.FieldByName('telefon').AsAnsiString), PAnsiChar(FDOrders.FieldByName('nazwa').AsAnsiString))
      else
        Application.MessageBox('Klient nie posiada przypisanego numeru telefonu.', 'Informacja', MB_ICONWARNING);
    end;
  end
  else
    Application.MessageBox('Plugin jest niedostępny.', 'Informacja', MB_ICONINFORMATION);
end;

Przez szukanie pochodnej interfejsu chodziło mi o QueryInterface

Plugin.Int.QueryInterface(IID_ISettings, Plugin.IntSettings)

Tutaj problemów nie ma, mój problem polega na tym, że nie wiem w jaki sposób w DLL z formy frmSendSMS odwołać się do implementacji pluginu z której okno było tworzone. Schemat dokładnie taki jak w opisie problemu.

1

Ty nie masz się do interfejsu odwoływać tylko musisz mieć KONKRETNY obiekt (instancję klasy) ten interfejs implementujący. Czyli na dobrą sprawę powinieneś mieć zamiast
SMS.Start(APhoneNumber, AReceiverName);
tak
SMS.Start(Self, APhoneNumber, AReceiverName);

Gdzie pierwszy parametr w metodzie Start powinien mieć typ IPluginSMS

Poza tym czytam te Twoje wątki o pluginach od jakiegoś czasu i jedyne co z nich wynika to to, że pojęcia nie masz co robisz. Masz jakieś podstawy, potrafisz wyklikać sobie formy, znalazłeś jakieś przykładowe kody i źródła ale nie rozumiesz ani ich ani nie ogarniasz co to jest klasa, obiekt, interfejs, czym się różnią, do czego są i jaka mechanika między nimi zachodzi.

0

Wiesz, nie każdy jest od razu we wszystkim zaje***, może Ty, ale ja nie jestem. Wolę od razu iść na głęboką wodę bo wtedy wiem, że muszę nauczyć się pływać, bo inaczej nic z tego nie będzie. Próbuje ten kod jakoś ogarnąć, interfejsy są dla mnie nowe, więc je poznaje, a to że na przykładzie wtyczek - to źle? Ja tak nie uważam. Jeżeli z tych wątków wynika, że nie mam pojęcia co robię, to może zamiast krytykować podrzuciłbyś ciekawy artykuł, który mi pomoże. Nie wiem czy wiesz, ale forum jest od pomagania, a Ty jako stary wyjadacz powinieneś służyć przede wszystkim pomocą, a nie krytyką, jaka często rzuca się w oczy czytając Twoje odpowiedzi na posty.

Dzięki za przykład, wydaje się logiczny - sprawdzę.

0

@abrakadaber: Dzięki o to mi chodziło. Tak patrzę na ten kod, który podałeś i zastanawiam się, jak mogłem tego nie wiedzieć.... Robiłem tak wiele razy, ale może dlatego nie wpadło mi to do głowy, bo siedzę non stop teraz przy interfejsach i DLL i napotykam wiele problemów z którymi walczę nie raz całymi dniami i po prostu głowa ma dość.

1
user322 napisał(a):

Wolę od razu iść na głęboką wodę bo wtedy wiem, że muszę nauczyć się pływać, bo inaczej nic z tego nie będzie. Próbuje ten kod jakoś ogarnąć, interfejsy są dla mnie nowe, więc je poznaje, a to że na przykładzie wtyczek - to źle?

Tak, to źle bo przez analogię do pływania to jesteś w sytuacji, gdzie próbujesz się nauczyć pływać ale nawet nie wiesz, że w wodzie nie możesz oddychać i nie zdajesz sobie sprawy, że musisz głowę utrzymać nad powierzchnią wody albo umrzesz, bo się po prostu tego wcześniej nie dowiedziałeś. Masz duże braki w podstawach i to od nich powinieneś zacząć. Interfejsy i biblioteki to jest coś cięższego kalibru, coś co wymaga przede wszystkim zrozumienia podstaw. Interfejsy w Delphi to nie są "wykastrowane" klasy jak np. w C#. One tutaj rządzą się trochę innymi prawami

Ja tak nie uważam. Jeżeli z tych wątków wynika, że nie mam pojęcia co robię, to może zamiast krytykować podrzuciłbyś ciekawy artykuł, który mi pomoże.

A co ciężko znaleźć samemu? Ja nie wiem co Ty uważasz, że wiesz, nie wiem co przerabiałeś, nie wiem co wcześniej robiłeś. Jednak najpierw podstawy obiektowości - klasy, enkapsulacja, dziedziczenie, czym się różni pole od właściwości, poziomy dostępu. Możesz poczytać np. tu OOP . Są przecież nawet wideotutoriale więc nic tylko siedzieć i oglądać. Zdajesz sobie sprawę, że zwykłą forma też jest klasą i podlega wszystkim jej prawom (z czego dość często początkujący nie do końca sobie zdają sprawę)

Nie wiem czy wiesz, ale forum jest od pomagania, a Ty jako stary wyjadacz powinieneś służyć przede wszystkim pomocą,

Dostałeś pomoc - konkretną linijkę, którą trzeba zmienić i co, gdzie dopisać.

a nie krytyką, jaka często rzuca się w oczy czytając Twoje odpowiedzi na posty.

Gdzie widzisz krytykę - ja tam stwierdzam fakty - nie masz podstaw a bierzesz się za rzeczy skomplikowane i stąd Twoje problemy

1 użytkowników online, w tym zalogowanych: 0, gości: 1