2011-11-20 16 views
6

Próbuję zapisać pinvoke dla metody ITaskTrigger :: GetTriggerString (zdefiniowane na http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx). Jeśli spojrzysz na stronę, to mówi ona, że ​​wywołujący metodę jest odpowiedzialny za zwolnienie pamięci (przez CoTaskMemFree) z LPWSTR, do którego odwołuje się pierwszy argument. Chociaż mogłem to zrobić ręcznie w .NET lub mogłem napisać mój niestandardowy marshaler za pomocą ICustomMarshaler, zastanawiałem się, czy użycie atrybutu MarshalAs (UnmanagedType.LPWStr) dla tego konkretnego argumentu spowoduje odpowiednie zwolnienie pamięci.Czy przy użyciu pamięci czyszczenia MarshalAs (UnmanagedType.LPWStr)?

Czy ktoś może wnieść pewien wgląd?

+0

Zobacz, jak pracować z typem dynamicznym za pomocą COM Interop - może to znacznie ułatwić pisanie statyczne i zapewnia zarządzanie pamięcią. – weismat

+0

Czy masz jakieś odniesienia do tego ostatniego fragmentu? C# już zarządza pamięcią dla współdziałania COM i zawsze ma. Typy dynamiczne ułatwiają pracę z np. Interfejsem IDispatch, ale czy mają inne funkcje zarządzania pamięcią niż statyczne typy interopów? –

Odpowiedz

6

Po pierwsze: mówimy tu o COM Interop (ITaskTrigger jest interfejsem COM), a nie P/Invoke. Dla tych dwóch zasad obowiązują różne zasady, dlatego ważne jest, aby zachować je w dobrym stanie. Na przykład musisz zdefiniować wrappery C# dla całego interfejsu, a nie tylko żądaną metodę. Powinny one zacząć: pinvoke.net

Krótka odpowiedź brzmi: masz szczęście, ponieważ CLR powinien właściwie zająć się sprawami.

Dłuższa odpowiedź obejmuje różne typy układania, w zależności od typów parametrów, kierunków i atrybutów dodawanych do podpisów interopowych.

W tym przypadku typ parametru, który otrzymasz w wywołaniu, jest parametrem "out string", z atrybutem MarshalAs(UnmanagedType.LPWSTR). Gdy serwer COM ujawnia wywołanie, które ma parametr "out" o typie łańcucha LPWSTR, zakładając, że serwer utrzymuje koniec transakcji, przydzieli bufor pamięci z numerem CoTaskMemAlloc() i zwróci go tobie. (Jeśli był to inny typ ciągu, np. BSTR, to specyficzne wywołanie przydziału pamięci może być inne, ale podstawowa koncepcja jest taka sama.) W tym momencie jesteś odpowiedzialny za wyczyszczenie pamięci, kiedy już jej nie potrzebujesz, używając zgodnego połączenia CoTaskMemFree().

Jest to specjalny rodzaj operacji nazywany jest „zmiana odniesienia”: parametr wysyłasz w już jest parametrem odniesienia, ale serwer COM będzie zastąpić go z innym odniesienia. Dobre wyjaśnienie tego procesu można znaleźć w sekcji "Własność pamięci" pod adresem this MSDN magazine article. Jak widać z tego artykułu, gdy CLR otrzymuje dane z powrotem z parametru "out" w typie referencyjnym, uznaje, że bierze odpowiedzialność za uwolnienie tej pamięci. Podczas przekazywania tego wywołania do kodu zarządzanego używa on atrybutu MarshalAs, aby ustalić, że jest to wskaźnik typu string w postaci modelu LPWSTR w COM, i że powinien on zostać przydzielony przy użyciu CoTaskMemAlloc(). Po utworzeniu zarządzanego ciągu danych, wywoła on w Twoim imieniu CoTaskMemFree() na oryginalnym buforze. Dane, które otrzymasz, będą w pełni zarządzane i nie będziesz musiał zajmować się problemami własności.

+1

Dzięki za odpowiedź! To doskonale to wyjaśnia. – wwahammy

+1

Naprawdę dobre wyjaśnienie, dzięki. –

Powiązane problemy