Jak przetrwać egzamin z RSO (DCOM)

Oto algorytm postępowania w przypadku DCOM. Nazwy mogą się różnić, bo spisywałem z pamięci. Należy podchodzić do tego materiału krytycznie, mogłem gdzieś się pomylić albo o czymś zapomnieć…

SERWER:

1. Stwórz projekt ATL/COM (parametry chyba wszystkie domyślne).
2. PPK na projekcie (gdzieś po lewej w każdym razie)-> new ATL Object -> Simple Object
Opcje:
Threading: Apartment
Aggregation: domyślnie
Interface: Custom
Z pozostałych: ISupportErrorInfo trzeba zaznaczyć.
3. dodać odpowiednie struktury w pliku idl. Przykład dla struktury reprezentującej liczbę zespoloną i wektor liczb zespolonych:

typedef struct
{
   double re;
   double im;
} Complex;
 
typedef struct
{
   int size;
   [size_is(size)] Complex* data;
} ComplexArray;

Te struktury należy także dodać do interfejsu. Zakładając, że nasz interfejs nazywałby się IMyInterface,

    [
        object,
        uuid(95D814D7-1F0C-4FDA-BE4F-F21027C61855),

        helpstring("IMyInterface Interface"),
        pointer_default(unique)
    ]

    interface IMyInterface : IUnknown
    {
        struct Complex;
        struct ComplexArray;
    };

4. Dodać własne komunikaty o błędzie (można to zrobić kiedykolwiek) w idlu:
na początku pliku dodać:

#include<winerror.h>
#define MAKE_HRESULT_ERROR(nCode) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, nCode)

dalej:

typedef[uuid(JAKIS-NUMER-NAJLEPIEJ-PRZEPISAC-Z-KOMPONENTU-I-ZMIENIC-JEDNA-CYFRE) helpstring("Error codes")]
enum JakiśTamError
{
   PierwszyKodBledu = MAKE_HRESULT_ERROR(0x0200),
   DrugiKodBledu = MAKE_HRESULT_ERROR(0x0201),
} JakiśTamError;

5. Przełączyć się na widok Class View (po lewej), a następnie PPM na interfejs tym utworzonym obiekcie (ten zagnieżdżony) i wybrać new method. Zostawić HRESULT jako typ zwracany, dopisać argumenty (argument typu [out,retval] jako ostatni na liście i jako wskaźnik, czyli jeśli np. zwracasz liczbę double to musi to być double* ). Na przykład argumenty metody która przyjmuje dwie liczby całkowite i zwraca liczbę zespoloną mogłyby wyglądać w ten sposób:

[in] int re, [in] int im, [out,retval] Complex result

6. Zmienić w pliku z rozszerzeniem rgs odpowiednie zapisy, tak żeby wyglądały w ten sposób:

HKCU
{
   NoRemove Software
   {
       NoRemove Classes
       {
            MójKomponent.....
       }
   }
}

7. Wypełnić wnętrze.

Swój własny błąd zwraca się przez funkcję Error, czyli np.:

return Error("blad", IID_UtworzonyWcześniejObiektCOM, PierwszyKodBledu);

8. odpalić

KLIENT:

1. aplikacja konsolowa.
2. wyłączyć precompiled headers w własnościach projektu.
3. w pliku głównym dodać:

#import "ścieżka\do\pliku.tlb" no_namespace named_guids
#include<iostream>

4. main:

int main(int argc, char** argv)
{
   try
   {
       CoInitialize(NULL);
       IObiektCOMPtr pObiekt(CLSID_ObiektCOM); //chodzi o ten simple object utworzony w serwerze
       //...
       //zabawa z obiektem i wywoływanie jego metod
       //...
 
       COUninitialize();
   }
   catch(const _com_error& e)
   {
       std::cout << static_cast<char*>(e.Description()) << std::endl;         
       return -1;
   }
   return 0;
}

5. odpalić.

No, to zgrubsza tyle…

O ile nie zaznaczono inaczej, treść tej strony objęta jest licencją Creative Commons Attribution-Share Alike 2.5 License.