Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用封送处理复制字节数组。使用C#donds';行不通_C#_.net_Pinvoke_Marshalling - Fatal编程技术网

使用封送处理复制字节数组。使用C#donds';行不通

使用封送处理复制字节数组。使用C#donds';行不通,c#,.net,pinvoke,marshalling,C#,.net,Pinvoke,Marshalling,我使用的是一个非托管库,它可以生成灰度图像(大约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

我使用的是一个非托管库,它可以生成灰度图像(大约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
这里是我的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\u图像
struct工作正常。在以前的版本中,我尝试为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\u 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());
最后,我认为您计算的长度不正确。当然,您需要使用
高度*宽度
。另外,您还没有考虑颜色深度。例如,32位颜色将为每像素4字节

IntPtr ImageData = (IntPtr) (pImage.ToInt64() + 
    Marshal.OffsetOf(typeof(ABS_IMAGE), "ImageData").ToInt64());