6

参考如何在 C# 中从 byte[] 获取 IntPtr

我正在尝试将 IntPtr 引用的数据读入字节 [],然后再读回另一个 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;
}
4

2 回答 2

7

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

为此,获取数据的最简单方法是调用CopyMarshal 类的静态方法,将指向非托管数据的指针、要读取的索引和字节数以及预分配的字节缓冲区传递给将数据编组到。

至于获取数组的大小,正如Anton Tykhyy 在评论中指出的那样看起来(这里要非常小心)调用Twain.GlobalLock(hImage)正在使用分配的内存GlobalAlloc,这意味着您可以通过调用APIGlobalSize函数P/Invoke 层以获取大小。

如果它不是通过调用分配的东西的句柄,GlobalAlloc那么您需要找出Twain模块如何分配内存并使用适当的机制来确定IntPtr.

于 2010-12-08T16:18:37.177 回答
2

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

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

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

于 2010-12-08T16:17:22.350 回答