[英]Copying byte array with Marshal.Copy from IntPtr using C# doesn't work
我正在使用一個非托管庫,它可以生成灰度圖像(大約100x200像素,或多或少)。 圖像包含在結構中,在C中如下所示:
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
typedef unsigned int ABS_DWORD;
typedef unsigned char ABS_BYTE;
在這里我的C#包裝器結構:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public IntPtr ImageData;
}
ABS_IMAGE
圖像並對ABS_IMAGE
結構進行編組可以正常工作。 在以前的版本中,我嘗試使用固定長度的字節數組用於ImageData,有時會崩潰。 我想這發生了,因為圖像尺寸沒有修復。 現在我嘗試在以后讀取圖像字節數組,之后我可以計算實際的數組長度。 這里有相關代碼:
ABS_Type_Defs.ABS_IMAGE img =
(ABS_Type_Defs.ABS_IMAGE)Marshal.PtrToStructure(
pImage,
typeof(ABS_Type_Defs.ABS_IMAGE));
int length = ((int)img.Height - 1) * ((int)img.Width - 1);
byte[] data = new byte[length];
Marshal.Copy(img.ImageData, data, 0, length);
現在我的問題:每次我想執行Marshal.Copy讀取圖像字節時,我得到一個AccessViolationException
。
有沒有人有想法?
這就是正在發生的事情。 您的結構是所謂的可變長度結構。 像素數據在結構中包含內聯,從ImageData
的偏移量開始。
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
您的API返回pImage
,它是一個IntPtr
,指向ABS_IMAGE
類型的非托管數據。 但是,如果查看本機代碼,則會看到ABS_VARLEN
等於1
。 這是因為必須在編譯時靜態定義struct
。 實際上,像素數據的長度由高度,寬度和顏色計數字段確定。
您可以繼續使用Marshal.PtrToStructure
來獲取大多數字段。 但是你無法以這種方式獲得ImageData
字段。 這需要更多的工作。
相反地聲明這樣的結構:
[StructLayout(LayoutKind.Sequential)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public byte ImageData;
}
當您需要獲取圖像數據時,請執行以下操作:
IntPtr ImageData = pImage + Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData");
Marshal.Copy(ImageData, data, 0, length);
如果您尚未使用.net 4,則需要進行轉換以進行算術編譯:
IntPtr ImageData = (IntPtr) (pImage.ToInt64() +
Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData").ToInt64());
最后,我認為你的計算length
不正確。 當然你需要使用Height*Width
。 你還沒有考慮顏色深度。 例如,32位顏色將是每像素4個字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.