2011-11-20 16 views
6

ITaskTrigger :: GetTriggerString yöntemi (http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx'da tanımlanmış) için bir pinvoke yazmaya çalışıyorum. sayfaya baktığınız takdirde, yöntemin arayan ilk argüman yoluyla başvurulan LPWSTR ait (CoTaskMemFree aracılığıyla) bellek boşaltmak için sorumlu olduğunu söylüyor. Ben .NET elle bunu yapabilir veya ICustomMarshaler kullanarak özel Sıralayıcı yazabilirsiniz iken söz konusu argüman için MarshalAs (UnmanagedType.LPWStr) özelliğini kullanarak uygun şekilde ayrılan belleği serbest bırakır, ben merak ediyorum.MarshalAs (UnmanagedType.LPWStr) temizleme bellek kullanacak?

Herhangi biri biraz fikir verebilir mi?

+0

Dinamik türüyle COM Interop ile çalışmaya bakın - bu, işleri statik yazmadan çok daha kolay hale getirebilir ve bellek yönetimini de halledebilir. – weismat

+0

Son bit için herhangi bir referansınız var mı? C# zaten COM birlikte çalışma için bellek yönetimi yapar ve her zaman vardır. Dinamik türler, örneğin bir IDispatch arabirimi ile uğraşırken işleri kolaylaştırır, ancak aslında statik birlikte çalışma türlerinden farklı bellek yönetimi özelliklerine sahipler mi? –

cevap

6

İlk şeyler ilk: burada COM Interop hakkında konuşuyorsunuz (ITaskTrigger bir COM arabirimidir), P/Invoke değil. İkisi için farklı interop kurallar vardır, bu yüzden onları düz tutmak önemlidir. Örneğin, yalnızca istediğiniz yöntem için değil, tüm arabirim için C# interop sarmalayıcıları tanımlamanız gerekir. Başlamanız gerekenler: pinvoke.net

Kısa cevap, şanslısınız, çünkü CLR sizin için gereken şeyleri halletmelidir.

Daha uzun yanıt, COM türü kodunun, türlerin türlerine, yönlere ve birlikte çalışma imzalarınıza hangi özniteliklere bağlı olarak değiştiğini farklı türlerde sıralamayı içerir. Bu durumda

, aramayla ilgili alacak parametre türü bir MarshalAs(UnmanagedType.LPWSTR) özniteliği, bir " out string" parametredir. Bir COM sunucusu LPWSTR dize türünde bir "out" parametresi olan bir çağrı ortaya çıkardığında, sunucunun anlaşmanın sonunu tuttuğunu varsayarak, CoTaskMemAlloc() ile bir bellek arabelleği ayırır ve size döndürür. (Farklı bir dize türüyse, BSTR gibi, belirli bir bellek ayırma çağrısı farklı olabilir, ancak temel kavram aynıdır.) Bu noktada, artık belleğe ihtiyaç duymadığınız zaman temizlemekten siz sorumlusunuz, eşleşen CoTaskMemFree() aramayı kullanarak.

Bu "referans değişikliği" adı verilen operasyonun özel bir türüdür: İçinde gönderiyor parametresi zaten bir referans parametre olmakla COM sunucusu, bir farklı referansla yerine gidiyor. Bu işlem için iyi bir açıklama, this MSDN magazine article'un "Bellek Sahipliği" bölümünde bulunur. Eğer CLR bir başvuru türüne bir "out" parametresinden geri verileri aldığı yazıda, görebileceğiniz gibi, bu o bellek boşaltmak için sorumluluk alma olduğunu kabul etmektedir. Yönetilen koda geri çağrılan marshaling işlemi sırasında, bunun COM'da LPWSTR dizgecik işaretçisi olduğunu ve bu nedenle CoTaskMemAlloc() kullanılarak ayrılması gerektiğini belirlemek için MarshalAs özniteliğini kullanır. Verilerin dışarı yönetilen bir dize oluşturduktan sonra, bu sizin adınıza orijinal tampon üzerinde CoTaskMemFree() arayacak. Geri aldığınız veriler tamamen yönetilecek ve herhangi bir mülkiyet sorunuyla uğraşmak zorunda kalmayacaksınız.

+1

Cevabınız için teşekkürler! Bu mükemmel bir şekilde açıklıyor. – wwahammy

+1

Gerçekten çok iyi bir açıklama, teşekkürler. –