2016-03-09 27 views
0

我發現許多方式從byte[]得到一個IntPtr的,所有這些我能成功地傳遞到外部非託管代碼得到一個非零IntPtr的,但只有如果我在堆棧上分配byte[]。試圖在byte[]實例變量上做同樣的事情,我得到了一個nullIntPtr.Zero)的結果,無論採用哪種方法獲得我選擇的IntPtr。在這種情況下,我還沒有發現任何關於實例變量是否與堆棧中分配的值不同的信息。似乎無法從一個byte []實例變量

這裏是我想用它來獲取有效的IntPtrbyte[]實例變量是什麼:

GCHandle pinned = GCHandle.Alloc(outBytes, GCHandleType.Pinned); 
IntPtr ptr = pinned.AddrOfPinnedObject(); 

// Always true, for reasons I'm unaware. 
if (ptr == IntPtr.Zero) {} 

pinned.Free(); 

謝謝!

+0

通過「在堆棧上」你的意思是用'stackalloc'? –

+0

我的意思是在本地範圍聲明一個byte [],就像這樣:'byte [] outBytes = new byte [GetNumBytes()]''。考慮到我正在使用'new',我的術語可能不正確。 –

+2

你可以給一個代碼示例,這不起作用嗎?它是一個全球陣列嗎?對象的成員?傳入函數的引用? –

回答

1

GCHandle.Alloc(thing, GCHandleType.Pinned)導致IntPtr.Zero的句柄的唯一時間是thing爲空時。您提供GCHandle.Alloc()時,您的字節數組引用爲空。

在此處,它返回零:

public class ZeroTest 
{ 
    private byte[] someArray; 

    public Test() 
    { 
     this.someArray = null; 
    } 

    public void DoMarshal() 
    { 
     GCHandle handle = GCHandle.Alloc(this.someArray, GCHandleType.Pinned); 

     try 
     { 
      // Prints '0'. 
      Console.Out.WriteLine(handle.AddrOfPinnedObject().ToString()); 
     } 
     finally 
     { 
      handle.Free(); 
     } 
    } 
} 

這裏就是返回非零:

public class Test 
{ 
    private byte[] someArray; 

    public Test() 
    { 
     this.someArray = new byte[1]; 
    } 

    public void DoMarshal() 
    { 
     GCHandle handle = GCHandle.Alloc(this.someArray, GCHandleType.Pinned); 

     try 
     { 
      // Prints a non-zero address, like '650180924952'. 
      Console.Out.WriteLine(handle.AddrOfPinnedObject().ToString()); 
     } 
     finally 
     { 
      handle.Free(); 
     } 
    } 
} 
+0

再次通過我的代碼來充實我上面的代碼對我來說確實揭示了我的錯誤。在我想要初始化成員變量的地方,我是在聲明一個局部變量,所以我的成員變量確實是'null'。我想我應該吃點東西......感謝您的幫助! –