引用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;
}
答案 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应提供此信息。