簡體   English   中英

可以在不執行Marshal.Copy的情況下將IntPtr轉換為字節數組嗎?

[英]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 ++代碼的指針。

嘗試這個:

byte* b = (byte*)intPtr;

需要不安全 (在函數簽名,塊或編譯器標志/unsafe )。

您不能讓托管陣列占用非托管內存。 您可以一次復制一個塊的非托管數據,並處理每個塊,或者創建一個UnmanagedArray類,該類接受IntPtr並提供仍將使用Marshal.Copy訪問數據的索引器。

正如@Vinod指出的那樣,您可以使用unsafe代碼執行此操作。 這將允許您使用類似C的指針直接訪問內存。 但是,在調用任何不安全的.NET方法之前,您需要將數據封送到托管內存中,因此您幾乎只限於自己的類C代碼。 我認為你根本不應該為此煩惱,只需用C ++編寫代碼即可。

查看此“代碼項目”頁面,了解使用非托管陣列的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM