[英]Can IntPtr be cast into a byte array without doing a Marshal.Copy?
我想從IntPtr指針獲取數據到字節數組。 我可以使用以下代碼來執行此操作:
IntPtr intPtr = GetBuff();
byte[] b = new byte[length];
Marshal.Copy(intPtr, b, 0, length);
但是上面的代碼強制從IntPtr到字節數組的復制操作。 當有問題的數據很大時,這不是一個好的解決方案。
有沒有辦法將IntPtr轉換為字節數組? 例如,以下工作:
byte[] b = (byte[])intPtr
這將消除復制操作的需要。
另外:我們如何確定IntPtr指向的數據長度?
正如其他人所提到的,你無法在不復制的情況下將數據存儲在托管 byte[]
(使用你提供的當前結構*)。 但是,如果您實際上不需要它在托管緩沖區中,則可以使用unsafe
操作直接使用非托管內存。 這真的取決於你需要做什么。
所有byte[]
和其他引用類型都由CLR垃圾收集器管理,這是在不再使用時負責內存分配和釋放的原因。 GetBuffer
返回指向的內存是由C ++代碼分配的非托管內存塊,(除了內存布局/實現細節)基本上與GC托管內存完全分開。 因此,如果要使用GC托管CLR類型( byte[]
)來包含IntPtr
指向的非托管內存中當前保存的所有數據,則需要將其移動(復制)到GC知道的內存中。 這可以通過Marshal.Copy
或使用unsafe
代碼或pinvoke的自定義方法或您擁有的內容來完成。
但是,這取決於你想用它做什么。 你已經提到了它的視頻數據。 如果要對數據應用某些轉換或過濾器,則可以直接在非托管緩沖區上執行此操作。 如果要將緩沖區保存到磁盤,則可以直接在非托管緩沖區上執行此操作。
關於長度的主題,除非分配緩沖區的函數也告訴您長度是多少,否則無法知道非托管內存緩沖區的長度。 這可以通過許多方式完成,正如評論者所提到的(結構的第一個領域,方法的參數)。
*最后,如果您可以控制C ++代碼,則可以對其進行修改,以便它不負責分配將數據寫入的緩沖區,而是提供指向預分配緩沖區的指針。 然后,您可以在C#中創建一個托管 byte[]
,預分配到C ++代碼所需的大小,並使用GCHandle
類型將其固定並提供指向C ++代碼的指針。
您不能讓托管陣列占用非托管內存。 您可以一次復制一個塊的非托管數據,並處理每個塊,或者創建一個UnmanagedArray
類,該類接受IntPtr
並提供仍將使用Marshal.Copy訪問數據的索引器。
正如@Vinod指出的那樣,您可以使用unsafe
代碼執行此操作。 這將允許您使用類似C的指針直接訪問內存。 但是,在調用任何不安全的.NET方法之前,您需要將數據封送到托管內存中,因此您幾乎只限於自己的類C代碼。 我認為你根本不應該為此煩惱,只需用C ++編寫代碼即可。
查看此“代碼項目”頁面,了解使用非托管陣列的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.