Verwenden von nicht verwalteten Zeigern in C++/CLI (gelöst)
-
Hallo,
ich habe vor ein paar Wochen wieder angefangen mich in Visual C++ einzuarbeiten.
Das aktuelle Projekt soll DirectShow verwenden.Mein kleines Problem ist nun folgendes, ich habe folgende Klasse:
ref class CapSource : COMClass, Interfaces::IDSSource { private: IBaseFilter* pSource; AM_MEDIA_TYPE* pMediaFormat; public: CapSource(); CapSource(System::String^); CapSource(int); CapSource(IBaseFilter* pSource); CapSource(System::String^, Types::DSVideoFormat, int); CapSource(int, Types::DSVideoFormat, int); CapSource(IBaseFilter*, Types::DSVideoFormat, int); CapSource(IBaseFilter*, AM_MEDIA_TYPE*, int); virtual IBaseFilter* getSourceFilter(); bool setVideoFormat(Types::DSVideoFormat, int); }; // class CapSource
desweiteren folgende Zeile in der Methode setVideoFormat(...)
pConfig->GetFormat(&pMediaFormat);
Besagte Zeile ruft nun folegende Compiler-Fehler hervor
error C2664: 'IAMStreamConfig::GetFormat': Konvertierung des Parameters 1 von 'cli::interior_ptr<Type>' in 'AM_MEDIA_TYPE **' nicht möglich
Bisher habe ich den Fehler umgangen in dem ich eine lokale Variable(Zeiger) erzeigt habe und diesen für den Aurfuf verwende.
AM_MEDIA_TYPE* pTempMedia; pConfig->GetFormat(&pTempMedia); pMediaFormat = pTempMedia;
Funktioniert zwar, finde ich aber wenig praktikabel. Gibt es eine bessere Methode um evtl die Member-Variabel direkt zu verwenden ?
MfG
Marco
-
Ja, das Problem ist, dass
pMediaFormat
auf dem so genannten GC-Heap liegt und jederzeit verschoben werden kann. Darum darfst du nicht einfach einen Zeiger darauf benutzen. Die Lösung: Den Speicher explizit pinnen und dann einen Zeiger benutzen...cli::pin_ptr<AW_MEDIA_TYPE *> pin_pMediaFormat = &pMediaFormat; // AW_MEDIA_TYPE *ptr_pMediaFormat = pin_pMediaFormat; pConfig->GetFormat(pin_pMediaFormat);
Weiss nicht, ob das so viel bequemer ist. Sobald dein
cli::pin_ptr
das Scope verlässt, könnten deine Zeiger ungültig werden, also nicht cachen oder soMfG
-
Danke für deine Antwort.
Ich weiss noch nicht ob ich das nun richtig verstanden habe.
Da ich 'pMediaFormat' als Member von 'CapSource' habe und diese Klasse eine managed-Klasse ist wird der Zeiger automatsich zu interior_ptr und landet auf dem GC-Heap.
Wenn der GC nun 'pMediaFormat' verschiebt, verschiebt er nur die Adresse von 'pMediaFormat' oder auch die Daten auf die gezeigt wird?
pin_ptr habe ich so verstanden das dem GC gesagt wird er soll das Objekt(Zeiger) nicht verschieben. Ist denke ich bei mir sinnvoll, da 'GetFormat' ein Methode aus DirectShow ist. MSDN-Link
Es kann also passieren das der GC den Pointer verschiebt während DirectShow die Daten reinschreibt....Sobald dein cli::pin_ptr das Scope verlässt, könnten deine Zeiger ungültig werden ...
Wenn ich den pin_ptr in der Methode erstelle wird er ja ganz sicher nach verlassen der Methode ungültig. Aber was passiert mit 'pMediaFormat' der ja ein Member der Klasse ist, wird dieser dann auch ungültig ?
MfG
-
Marco K. schrieb:
Wenn der GC nun 'pMediaFormat' verschiebt, verschiebt er nur die Adresse von 'pMediaFormat' oder auch die Daten auf die gezeigt wird?
Nur den Zeiger selbst, der Speicher auf den per nativen Zeiger gezeigt wird nicht. Um den Zeiger und dessen Gültigkeit musst du dir also keine Gedanken machen. Ein Zeiger auf diesen Zeiger stellt aber eine andere Situation dar. Wenn ich von ungültigen Zeigern spreche, so meine ich ausschliesslich das Resultat von
&pMediaFormat
. Benutzpin_ptr
und du bist auf der sicheren SeiteMfG
-
Danke dir hast mich extrem weiter gebracht
MfG
Marco