[VS2008/C++] Konwersja typów "managed - unmanaged"

0

Cały czas bawię się z DirectShow. Chciałem go użyć w Windows Form Application. Na początek, w ramach prób, chciałem, aby po naciśnięciu jakiegoś przycisku móc oglądać materiał filmowy.
Próbuję zaimplementować kod ze strony MS http://msdn.microsoft.com/en-us/library/ms783787.
Funkcja programująca button wygląda następująco:

private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
				 
        hr = CoInitialize(NULL);
	if (FAILED(hr))
	{
		label1->Text="Błąd wywołania funkcji CoInitialize() !!!";
	}
	hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); //BŁĄD KOMPILATORA
	if (FAILED(hr))
	{
		printf("ERROR - Could not create the Filter Graph Manager.");
		return;
	}

	hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);//BŁĘDY
	hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);     //KOMPILATORA
	hr = pGraph->RenderFile(L"D:\\Filmy\\jakis.avi", NULL);

	if (SUCCEEDED(hr))
	{
		// Run the graph.
		hr = pControl->Run();
		if (SUCCEEDED(hr))
		{
			// Wait for completion.
                        long evCode;
                        pEvent->WaitForCompletion(INFINITE, &evCode);
		}
	}
	pControl->Release();
	pEvent->Release();
	pGraph->Release();
	CoUninitialize();
}

Wcześniej deklaruję:

public: HRESULT hr;
private: IGraphBuilder *pGraph;
private: IMediaEvent   *pEvent;
private: IMediaControl *pControl;

Niestety, następuje błąd kompilatora:

error C2440: 'type cast' : cannot convert from 'cli::interior_ptr<Type>' to 'void **'

Cannot convert a managed type to an unmanaged type
a dokładnie trzy takie błędy, przy próbie wywoałań funkcji: CoCreateInstance() oraz QueryInterface().

Czy da się coś z tym zrobić?

Próbowałem *pGraph definiować jako void i dopiero po wywołaniu funkcji CoCreateInstance rzutować na typ IGraphBuilder, ale wtedy był błąd rzutowania do typu LPVOID * podczas wywołania funkcji CoCreateInstance...

0

na chłopski rozum, bo nie kompiluje mi się to ze względu na brak DirectX SDK:

pin_ptr<IGraphBuilder*> pGraph_pin = &pGraph;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)pGraph_pin);

pin_ptr<IMediaEvent*> pEvent_pin = &pEvent;
pin_ptr<IMediaControl*> pControl_pin = &pControl;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)pControl_pin);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)pEvent_pin);

albo trzymaj te interfejsy jako zmienne lokalne lub pola klasy natywnej (typu class

 a nie <code noframe>ref class

). problem jest stąd, że operator &

 na polu klasy zarządzanej nie zwraca wskaźnika typu <code noframe>*

, tylko interior_ptr<>

.
0

No dobra, zrobiłem z interfejsów zmienne lokalne i zadeklarowałem je wewnątrz funkcji programującej naciśnięcie buttona.

Zrobiłem również drugą wersję i stworzyłem własną klasę i tam normalnie zdefiniowałem te interfejsy jako pola klasy i stworzyłem funkcję odtwarzajFilm() ze wspomnianym kodem umożliwiającym odtworzenie filmu. W funkcji programującej buttona tylko wywoływałem tą funkcję na rzecz obiektu klasy którą stworzyłem.

Skompilowało się, ale niestety, problem jest tym razem z linkerem (w obu przypadkach taki sam), a mianowicie

error LNK2020: unresolved token (0A000014) IID_IMediaEvent
1>error LNK2020: unresolved token (0A000015) IID_IMediaControl
1>error LNK2020: unresolved token (0A000018) CLSID_FilterGraph
1>error LNK2020: unresolved token (0A000019) IID_IGraphBuilder
1>error LNK2001: unresolved external symbol IID_IMediaEvent
1>error LNK2001: unresolved external symbol IID_IMediaControl
1>error LNK2001: unresolved external symbol IID_IGraphBuilder
1>error LNK2001: unresolved external symbol CLSID_FilterGraph
1>C:\Users\xxxxxxx\xxx.exe : fatal error LNK1120: 8 unresolved externals

Wygląda na brak jakichś bibliotek, albo niewłaściwy tryb kompilacji - nie wiem, bo dodałem zarówno <dshow.h> jak i linkuję z bibliotekami Strmiids.lib oraz Quartz.lib. Szukam w necie, ale jak dotąd nie znalazłem nic co by mi mogło pomóc. Znalazłem tylko wypowiedź kogoś na forum z podobnym problem i napisał coś takiego:

I solved the problem: The library is per default compiled with /clr:pure
and the default for the executable ist /clr. If I compile the library
with /clr too, it work's fine so far.

Nie rozumiem tego jednak do końca. Nie wiem o co chodzi z "domyślną kompilacją z /clr". Jest ktoś w stanie mi pomóc?

0

Rozwiązałem ten problem. We właściwościach projektu w Configuration Properties -> General -> Project Defaults trzeba ustawić Common Language Runtime Suport na /clr, bo domyślnie jest /clr:pure. Niestety, nie wiem o co w tym chodzi i jak to działa, ale działa. Nie ma żadnych błędów a program działa tak jak chciałem.

0

parametr /clr:pure oznacza że wynikowy exe będzie zawierał wyłącznie kod zarządzalny. parametr /clr oznacza hybrydowy exe, w którym będzie zarówno natywny kod maszynowy jak i kod zarządzalny.
widocznie te interfejsy nie skompilują się w czystym CLR.
Skutkami ubocznymi hybrydowego exe są: fakt że bitowość (32/64) programu określamy w momencie kompilacji (framework nie będzie mógł dobierać jak chce bo te natywne fragmenty wymuszają architekturę), oraz że program nie ruszy na Mono.

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