IntPtr到字节数组和返回

时间:2010-12-08 16:09:24

标签: c# interop marshalling intptr

引用How to get IntPtr from byte[] in C#

我试图将IntPtr引用的数据读入byte []然后再返回另一个IntPtr。指针正在引用从扫描仪设备捕获的图像,因此我还假设捕获此信息应放入字节数组中。

我也不确定Marshal.SizeOf()方法是否会返回IntPtr引用的数据大小或指针本身的大小。

我的问题是我收到错误“类型'System.Byte []'无法编组为非托管结构;无法计算有意义的大小或偏移量”

IntPtr bmpptr = Twain.GlobalLock (hImage);

try
{
     byte[] _imageTemp = new byte[Marshal.SizeOf(bmpptr)];
     Marshal.Copy(bmpptr, _imageTemp, 0, Marshal.SizeOf(bmpptr));

     IntPtr unmanagedPointer = Marshal.AllocHGlobal(
         Marshal.SizeOf(_imageTemp));

     try
     {
           Marshal.Copy(_imageTemp, 0, unmanagedPointer, 
               Marshal.SizeOf(_imageTemp));

           Gdip.SaveDIBAs(
               string.Format("{0}\\{1}.{2}", CaptureFolder, "Test", "jpg"), 
               unmanagedPointer, false);
     }
     finally
     {
           Marshal.FreeHGlobal(unmanagedPointer);
     }
}
catch (Exception e)
{
      Scanner.control.Test = e.Message;
}

2 个答案:

答案 0 :(得分:6)

调用SizeOf引发的异常是正确的;该方法无法知道传递给它的数组的长度是多少,它只有一个指针。

为此,获取数据的最简单方法是调用静态Copy method on the Marshal class,将指针传递给非托管数据,索引和要读取的字节数,以及预先分配的缓冲区用于编组数据的字节数。

至于获取数组的大小,如Anton Tykhyy pointed out in the comments出现(在这里要非常小心),对Twain.GlobalLock(hImage)的调用使用{{1}分配的内存3}},这意味着您可以通过P / Invoke层调用GlobalAlloc来获取大小。

如果是通过调用GlobalAlloc分配的东西的句柄,那么你需要找出Twain模块如何分配内存并使用适当的确定IntPtr指向的内存长度的机制。

答案 1 :(得分:2)

1-我假设bmpptr已经是一个非托管指针,如果是这样,为什么你需要将其“往返”回一个非托管指针unmanagedPointer

2- Marshal.SizeOf不会给你非托管内存分配的大小。

使用Marshal.Copy,您可以将非托管内存的内容复制到托管字节数组,但您需要知道需要将多少字节从非托管缓冲区移动到托管缓冲区。理想情况下,API应提供此信息。