English 中文(简体)
正在与元帅复制字元数组。 从 IntPtr 使用 C# 复制 Cpy 无效
原标题:Copying byte array with Marshal.Copy from IntPtr using C# doesn t work

我使用一个未管理的库,该库生成灰度图像(约100x200像素,或多或少)。

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;
}

Grabbing the image and marshallign the ABS_IMAGE struct works just fine. In a previous version, I tried using a byte array with fixed length for ImageData, which crashed sometimes. This happened, I think, because the image size is not fix. Now I try to read the image byte array at later time, when I can calulate the real array length before. Here the relevant code:

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);

现在我的问题:每当我想处决元帅。 复制读取图像字节, 我就会得到一个 < code> AccessViolationExpendion 。

有谁知道吗?

最佳回答

这就是正在发生的情况。 您的像素结构是所谓的变量长度结构。 像素数据包含在像素结构中, 从偏移开始到 ImaageData

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 返回 < code> pImaage 是一个 < code> IntPr , 它指向类型 < code> ABS_ IMAGE 的未管理数据。 但是, 如果您查看本地代码, 就会看到 < code> ABS_ VARLEN 等于 < code> 1 。 这是因为 < code> struct 在编译时必须静态地定义。 实际上, 像素数据长度将由高度、 宽度和颜色计字段决定 。

您可以继续使用 Marshal.PtrToStructure 来获取大部分字段。 但是您无法在 ImagageData 字段中找到。 这将需要多一点工作 。

宣布这种支架:

[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());

最后,我认为您计算 < code> 长 时错误。 您当然需要使用 < code> h8* Width 。 您也没有计算颜色深度。 例如, 32 比特的颜色为每像素4字节 。

问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签