2010-07-13 441 views
7

假設在Native.dll中有一個C++方法int NativeMethod(double, double *)。我在調用從託管代碼這種方法第一次嘗試(假設我不需要指定入口點)正確使用DllImport

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, IntPtr outD); 

然後使用DLL我做

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); 
NativeMethod(2.0, x); 

//do stuff with x 

Marshal.FreeHGlobal(x); //crash 

我想明白爲什麼這裏崩潰了。我的第一個猜測是,這是一個堆問題,因爲DLL和我的應用程序可能使用不同的CRT。但是,如果是這種情況,爲什麼不調用NativeMethod崩潰呢?該方法返回一個x,我可以成功地從中提取double。

我能夠獲得進口通過將雙參照

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, IntPtr outD); 

工作爲什麼在第一次嘗試FreeHGlobal崩潰,以及什麼纔是指針傳遞給本地方法的推薦方式? out關鍵字可以正常工作,但如果我需要編組字符串呢?我不認爲我能得到周圍AllocH和弗裏...

+0

它給你什麼錯誤信息? – Amy 2010-07-13 14:54:02

+0

當然,這應該是typeof(雙)。但我認爲SizeOf(typeof(InpPtr))總是> = SizeOf(typeof(double)),所以它可能以某種方式工作。有趣的是,什麼是「用x做東西」的一部分? – 2010-07-13 15:00:02

回答

5

的問題是,該方法採用double*這是一個指向double的指針。您正在傳遞一個指向IntPtr的指針。這很重要,因爲double(8字節)和IntPtr之間的大小差異是可變大小(4或8字節)。您需要將指針分配給double

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)); 
+0

啊,非常感謝..我錯過了有關msdn參考中平臺特定大小的部分。 – insipid 2010-07-13 15:01:35

2

我不是專家,但它不應該是:

IntPtr x = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))); 
7

我可能會誤解你的目標,但似乎你是使它更復雜得多,是必要的。只需通過參考傳遞,讓下面的編組負責照顧它。

[DllImport("Native.dll")] 
private static extern int NativeMethod(double inD, ref double outD); 

double x; 

x = 1; 
NativeMethod(2.0, ref x); 
+0

+1最有代表性的是用來代替參考。 OP沒有初始化指針。 – JaredPar 2010-07-13 16:12:13

+0

@JaredPar,的確如此。我不確定OP是否需要ref或out行爲,但我沒有認識到這個明顯的線索(他沒有在例子中初始化它)。 – 2010-07-13 17:05:38

+0

使用out/ref與AllocHGlobal獲得無人值守的內存有什麼關係?在方法/函數返回之前,GC是否可以重新排列內存並更改指針引用? – 2010-07-15 15:30:26