2009-07-17 8 views
6

Próbuję zbudować aplikację, która używa komponentu COM w VisualStudio '05 w natywnym C++. Mieszanka natywnych i zarządzanych wyrażeń rzeczy w MSDN całkowicie zniszczyła mój mózg . (Myślę, że MSDN jest totalnym bałaganem pod tym względem). Potrzebuję krótkiej i prostej natywnej próbki kodu C++, aby załadować mój komponent i uczynić go użytecznym. Jestem w porządku z kompilatorem tworzącym opakowania i tym podobne.Jak mogę łatwo użyć komponentu COM w Native Visual C++

Proszę nie radzić mi używać przykładowego MFC opartego na dialogu, ponieważ nie działa z tym komponentem i sam w sobie jest ogromnym zbiorem c ... .

Czy może to być problem natywny com vs managed com?

jestem zupełnie zagubiony, proszę dać mi kilka łożysk ...

EDIT: Dzięki za wszelką pomoc. Moim problemem jest to, że wszystko, co mam, to zarejestrowana biblioteka dll (właściwie OCX, patrz poniżej) . Ja (osobiście) znam jaki interfejs powinien wyglądać, ale jak mam przekazać mój program? Brak nagłówków, które definiują identyfikatory interfejsów, z których mogę korzystać. Ale czytałem, że kompilator C++ może go wyodrębnić i owinąć. Czy ktoś wie, jak to się robi?

WYJAŚNIENIE: Mam tylko OCX i wskazówkę z dokumentacji komponentu, jakie metody powinien on ujawnić.

Odpowiedz

3

przykładem w pełni funkcjonalny (dokładnie to, czego potrzebujesz) z moim blogu artykuł: How to Call COM Object from Visual Studio C++?

// https://helloacm.com/how-to-call-com-object-from-visual-studio-c/ 
#include <iostream> 
#include <objbase.h> 
#include <unknwn.h> 
#include <Propvarutil.h> 
#import "wshom.ocx" no_namespace, raw_interfaces_only 

using namespace std; 

int main() { 
    HRESULT hr; 
    CLSID clsid; 
    CoInitializeEx(nullptr, COINIT_MULTITHREADED); 
    CLSIDFromProgID(OLESTR("WScript.Shell"), &clsid); 
    IWshShell *pApp = nullptr; 
    hr = CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWshShell), reinterpret_cast<LPVOID *>(&pApp)); 
    if (FAILED(hr) || pApp == nullptr) { 
     throw "Cannot Create COM Object"; 
    } 
    int out; 
    VARIANT s; 
    InitVariantFromInt32(0, &s); 
    VARIANT title; 
    InitVariantFromString(PCWSTR(L"title"), &title); 
    VARIANT type; 
    InitVariantFromInt32(4096, &type); 
    BSTR msg = ::SysAllocString(L"Hello from https://helloacm.com"); 
    pApp->Popup(msg, &s, &title, &type, &out); 
    CoUninitialize(); 
    cout << "Out = " << out; 
    return 0; 
} 
3

Cieszę swoje wysiłki, aby przejść z macierzystym C++ do czynienia z COM - trzeba przejść przez ból, aby naprawdę docenić dzisiejsze luksusowy (zarządzanych) środowisko programistyczne :)

Powrót kiedy świat (i) były młodsza, książka Kraiga Brockshmidta "Inside OLE" była z tomem dla wyczucia COM (przed COM nawet był COM). Ta książka poprzedza zarządzany kod, więc nie ma tutaj szans na zdezorientowanie. Jest też drugie wydanie.

Książki Don Box "Essential COM" i "Effective COM" były później, ale mile widziane dodatki do sklepu (niezarządzanego) wiedzy COM.

Jeśli jednak twój portfel nie obejmuje kupowania tych zakurzonych starych książek, materiał instruktażowy COM COM: here może pomóc Ci ustawić właściwą drogę.

Happy hacking.

+0

Dobrze. Dzięki :). Mógłbym powiedzieć: "Nie czytam!" ale to nie byłoby dobre posunięcie w karierze;) – AndreasT

2

Nagie minima dla instancji obiektu COM są następujące:

1) musi mieć mieszkanie COM dostępne.

Jest to realizowane przez większość aplikacji, wywołując CoInitialize/CoInitializeEx, aby skonfigurować bibliotekę COM i początkowe mieszkanie COM, jeśli jest to pierwszy proces.

2) Wywołaj CoCreateInstance/CoCreateInstanceEx, aby utworzyć obiekt, i określ flagi, aby wskazać, w jaki sposób zostanie utworzona instancja.

3) Prawidłowe zbalansowanie wywołań AddRef i Release na interfejsach wszystkich utworzonych składników COM, wywołanie ostatniego wydania() po zakończeniu korzystania z komponentu COM.

-

W zarządzanej aplikacji, # 1 jest prawie zawsze obsługiwane dla Ciebie. # 2 jest wyodrębniany, jeśli zaimportujesz odniesienie do biblioteki COM i możesz po prostu użyć zaimportowanych nazw, tak jakby były definicjami klasy .NET i innymi. # 3 jest automatycznie obsługiwany, ale Twoje potrzeby mogą się różnić. Niestety, czasami zdarza się, że referencje są obsługiwane w aplikacjach zarządzanych, co może powodować, że obiekty COM będą się utrzymywać dłużej niż zamierzano. Klasa pomocników Marshal w System.Runtime ma metody, które mogą ci pomóc, jeśli napotkasz problemy.

-

W niezarządzanych aplikacji, trzeba będzie zrobić kilka legwork jeśli tworzysz aplikację od podstaw.

  1. Zadzwoń CoInitialize/CoInitializeEx na początku głównego wątku aplikacji, aby skonfigurować mieszkanie.
  2. Gdy główny wątek aplikacji wkrótce się zakończy, wywołaj funkcję CoUninitialize(), aby zamknąć mieszkanie.
  3. Aby utworzyć dodatkowe wątki, należy również wywołać CoInitialize/CoInitializeEx po uruchomieniu, jeśli trzeba użyć obiektów COM z tych wątków. Ponadto, w zależności od aplikacji, możesz ustawić parametry mieszkania.
  4. W przypadku tych wątków również wywołaj funkcję CoUninitialize(), gdy są one poprawnie zamykane.
1

Pomoże Ci, jeśli podasz trochę więcej informacji o tym, co dokładnie robisz. Czy wiesz, jakie interfejsy implementuje obiekt, itp?

Ogólnie rzecz biorąc, API, które można uzyskać w Google, aby uzyskać bardziej szczegółową pomoc, to CoCreateInstance. Musisz przekazać identyfikator GUID obiektu, z którym chcesz grać. Wszystkie obiekty COM implementują interfejs IUnknown i można zapytać o wszelkie inne, jakie może mieć. Tak więc niektóre próbki pseudokod, aby zacząć grę może wyglądać:

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
CoCreateInstance(CLSID, 
         ptrIUnknown, 
         ClassCxt, // generally CLSCTX_INPROC_SERVER, 
         riid , // reference id 
         (void **)&pRequest); // the interface that corresponds to the riid 

Tutaj można wyszukać dodatkowe interfejsy za pomocą interfejsu IUnknown uzyskanego z ptrIUnknown.

Następnie oczyścić z olejkami COM

CoUninitialize() 

Don Box jest to świetna książka na ten temat. Ponadto, tylko do testowania działania twojego obiektu COM, użycie czegoś takiego jak VBScript sprawia, że ​​jest to bardzo łatwe. Warto również zauważyć, że identyfikator GUID klasy ID jest przechowywany w dość niecodzienny sposób, więc jeśli zgrywasz GUID z rejestru, możesz mieć problem z ustaleniem kolejności. To chyba jednak inna kwestia.

+1

Essential COM: +1 –

1

Używam kombinacji inteligentnych wskaźników COM ATL i klasy ATL :: CAxWindow dla obiektów i komponentów COM. Uważam, że inteligentne wskaźniki są szczególnie łatwe w użyciu.

http://www.murrayc.com/learning/windows/usecomfromatl.shtml

http://76.105.92.243/notes/atlcom.html#import

http://msdn.microsoft.com/en-us/library/yx242b61%28VS.80%29.aspx

+0

Dzięki za linki, numer 2 wygląda naprawdę obiecująco. Zajmie to do jutra, aby przeanalizować to wszystko: – AndreasT

+0

Chciałbym wiedzieć, dlaczego ktoś to skrytykował! Próbowałem tylko pomóc. – Rob

+0

Cóż, a ty się udało. Dzięki. – AndreasT

0

Spróbuj użyć #import z Visual C++. Spowoduje to utworzenie inteligentnych wrapperów pointer dla interfejsów.