Można przekazać składnik COM w wywołaniu funkcji jako wskaźnik.
Załóżmy, że zaimplementowałeś obiekt w swoim EXE i ładowałeś inny obiekt COM z biblioteki DLL, możesz przekazać obiekt oparty na EXE do obiektu z biblioteki DLL. Załadowany obiekt musiałby obsługiwać interfejs, który ma funkcję akceptującą wskaźnik, np.
interface ILoadedObject
{
HRESULT GiveObject(IUnknown *pObj);
};
Jeśli obiekt DLL oparte wdraża, że można nazwać to z EXE i przekazać obiekt , które nie są zarejestrowane w dowolnym, więc nie ma potrzeby rejestrowania obiektów w EXE do osiągnięcia tego celu .
Jedyne wymagania to na prawidłową realizację IUnknown
: nie zniszczyć obiekt aż Release
został nazwany odpowiednią liczbę razy, i upewnić się, że QueryInterface
może być używany do przechodzenia między stałym zestawem interfejsów na obiekcie i że zapytanie dla IUnknown
zawsze zwraca ten sam adres.
Z drugiej strony można zarejestrować EXE jako serwer obiektów, ale to wprowadza wiele złożoności; COM musi uruchamiać EXE, a następnie wysyłać wiadomości za pośrednictwem kolejki komunikatów systemu Windows. Jest to tylko szeroko stosowane w OLE; może być dość kruchy.
Aktualizacja
Pełniejszy rozwiązaniem jest zdefiniowanie standardowy sposób, aby utworzyć instancję typu obiektu, ale aby umożliwić EXE aby określić, jak to działa. EXE będzie realizować:
interface IComponent;
interface IEnvironment : IUnknown
{
HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}
Każdy element musi obsługiwać ten interfejs:
interface IComponent : IUnknown
{
HRESULT SetEnvironment(IEnvironment *pEnv);
}
Teraz, aby uzyskać standardowe zachowanie gdzie EXE chce korzystać z rejestru, aby znaleźć elementy, można go wdrożyć CreateInstance
Metoda taka jak ta:
HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
__uuidof(IComponent), (void **)&ppNew);
if (FAILED(hr))
return hr;
(*ppNew)->SetEnvironment(this);
return S_OK;
}
Ale oczywiście może to zmienić i "wstrzyknąć" niektóre elementy. Dlatego zamiast (lub oprócz) rejestru można użyć pliku konfiguracyjnego. Lub (jak prosiłem) EXE może mieć wbudowane implementacje niektórych komponentów:
Ponieważ każdy składnik jest powiadamiany o środowisku, gdy jest on utworzony, można go używać do tworzenia środowiska dalsze składniki:
// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
m_env = e; // using a smart pointer for ref-counting
return S_OK;
}
// in some method of the component
ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);
// now query button for more useful interface...
Zawsze, gdy komponent jest tworzony, środowisko (zdefiniowane w EXE) może kontrolować dokładnie, w jaki sposób można znaleźć implementację komponentu. Każde stworzenie przechodzi przez EXE.
Jest to czasami nazywane "wstrzyknięciem zależności" lub "odwróceniem kontroli".
Nie jestem pewien, czy pierwszy paragraf jest prawdziwy, ponieważ w artykule, do którego się on prowadzi, jedyne wzmianki o przetwarzających poza proces serwerach EXE mówią, że nie można ich używać z COM bez rejestracji. Ten wątek jest również użyteczne i wskazuje na problemy z ROT którego rejestrację wolne COM najwyraźniej zaniedbuje zarządzanie: http://social.msdn.microsoft.com/Forums/vstudio/en-US/3849f22d-c8b8-429e- a03a-37601411acec/registrationfree-exe-com-server- Wygląda na to, że podstawowe obiekty COM DLL są również obsługiwane przez mechanizm reg-free, a do wszystkiego, co bardziej egzotyczne, musisz przetasować. . –
Odpowiedzi dotyczące wyłącznie linków są naprawdę złe, ponieważ linki mają tendencję do znikania ... jak te w tej odpowiedzi. – Stephane