2012-08-15 46 views
13

İnterneti çok araştırdım ama iyi bir açıklama bulamadım.IntPtr yerine SafeHandle kullanabilir miyim?

Soruma son derece basit.

Initialize adlı bir işlevi olan bir DLL'im var ve parametrelerden biri, sonraki çağrılar için kullanılacak bir tanıtıcı alan bir işaretçi. Başka bir parametre, tamlık için listeleyeceğim bir dizedir. Ben kullanıyorum imza (basit formunda) şöyledir: ": kolu alacak bir konuma Pointer KOLU" yorum ile Initialize(LPTSTR name, HANDLE handle):

[DllImport(MyDll)] 
static extern bool Initialize([In] string name, out IntPtr handle); 

DLL kendisinde imza olarak yazılır.

Ve sonraki çağrılar

[DllImport(MyDll)] 
static extern bool DoSomething(IntPtr handle, uint randomParameter); 

Ben yaklaşık SafeHandle okuma edilmiş ve benim ıntptr kolu için substite için kullanabilir acaba şeklindedir. Ve eğer yapabilirsem, nasıl yapabilirim? Özet SafeHandle sınıfını genişletmek bir sorun değil, ancak Intellect for SafeHandle'ı (ve varsayılan Marshalling'i kullanmam) doğrudan ekleyebilir miyim, yoksa ekstra bir şey mi yapmam gerekiyor?

Burada SafeHandle ve IntPtr arasındaki farkla ilgili daha kapsamlı bir cevap bulabilirsiniz
+0

'yapar SafeHandle' sadece' IntPtr' saklamak size vermeye ne fayda değil? –

+4

@ScottChamberlain - 'SafeHandle '' IDisposable '' ve tanıtıcı tarafından atıfta bulunulan kaynakların serbest bırakılmasını sağlar.IntPtr, etrafından geçirilebilecek bir işaretçi büyüklüğünde bir değerdir - yok etme semantiği yoktur. – LBushkin

+0

Hafıza ücreti almanıza izin verildiğini varsayarak, “Marshal.FreeBSTR”, “Marshal.FreeCoTaskMem” veya “Marshal.FreeHGlobal” kullanarak işaretçi belleğini ayırmadıkça, güvenli bir şekilde belleği C# ile ayırın. 'IntPtr' kullanıldığında, C# otomatik olarak herhangi bir belleği boşaltmaya çalışmaz. – Pooven

cevap

10

: Ancak IntPtr, SafeHandle and HandleRef - Explained

, argüman aslında makine boyutlu işaretçisi olduğunda IntPtr kullanılması gerektiğini, özetlemek-SafeHandle olmalıdır argüman aslında bir Win32 tanıtıcısı nerede kullanılır. Bu tipler genellikle birbirleriyle değiştirilemez; IntPtr boyutu, farklı mimarilere göre değişecektir (x64 ve 32 bit x64 ve 64 bit). NOT: Kapakların altında, SafeHandle'un da bir IntPtr kullanacağına inanıyorum). Ayrıca, IntPtr, SafeHandle'dan farklı olarak, bir tür çöp toplandığında gerçekten kaynakların atılmasını gerçekleştirir. Bu, program çalışıyorken sistem kaynaklarının sızdırılmamasını sağlar (Dispose()SafeHandle örneğinin mümkün olduğunda erken olması gerekir). SafeHandle'un aslında soyut olduğuna dikkat edin, çünkü uygun bertaraf ve kullanım için farklı yaklaşımlar gerektiren birçok farklı tür tutamağı vardır. Özel durumunuzda, aradığınız DLL dosyasının belgelerine bakmanız gerekmektedir. Win32 DLL ise, zaten bir SafeHandle türü olabilir. Üçüncü taraf bir DLL ise, o zaman kendi SafeHandle uygulamanızı yuvarlayabilirsiniz - Initialize()'a ek olarak Release() (veya eşdeğeri) bir sürümü olduğunu varsayarak.

SafeHandle vs IntPtr hakkında bazı ek ilginç bilgiler

bulunabilir:

Use SafeHandle to encapsulate native resources

SafeHandle Class Reference

SafeHandles and Critical Finalization

+0

Kesinlikle "IntPtr" 64 bit değil 65 mi? Düzenlemeyi yaptım - lütfen geri dönün ve daha fazlasını açıklayın (bunun için her gün yeni bir şeyler öğrenmek için hazırlanıyorum) – sblom

+0

Söylediğim gibi kendi SafeHandle implentasyonumun yaratılması büyük bir şey değil, bolca örnek var. Bilmek istediğim, SafeHandle ve IntPtr'i birbirinin yerine kullanabiliyor olsaydım, bu yüzden şunu yapabilirdim: 'statik extern bool Initialize (Statik extern boole Initialize) [In] dize adı, IntPtr) '? – Davio

+0

@sblom: Hayır, bu sadece benim tarafımdaki bir yazım hatasıydı. Onu yakaladığın için teşekkürler. – LBushkin

İlgili konular