C# IntPtr到字节数组并返回
参考 我试图将IntPtr引用的数据读入字节[],然后读回另一个IntPtr。指针引用的是从扫描仪设备捕获的图像,因此我还假设捕获此信息应放在字节数组中 我也不确定Marshal.SizeOf()方法是否返回IntPtr引用的数据大小或指针本身的大小 我的问题是收到错误“Type”System.Byte[]”无法作为非托管结构封送;无法计算有意义的大小或偏移量C# IntPtr到字节数组并返回,c#,interop,marshalling,intptr,C#,Interop,Marshalling,Intptr,参考 我试图将IntPtr引用的数据读入字节[],然后读回另一个IntPtr。指针引用的是从扫描仪设备捕获的图像,因此我还假设捕获此信息应放在字节数组中 我也不确定Marshal.SizeOf()方法是否返回IntPtr引用的数据大小或指针本身的大小 我的问题是收到错误“Type”System.Byte[]”无法作为非托管结构封送;无法计算有意义的大小或偏移量 1-我假设bmpptr已经是非托管指针,如果是,为什么需要将其“往返”回非托管指针unmanagedPointer 2-Marshal.
1-我假设
bmpptr
已经是非托管指针,如果是,为什么需要将其“往返”回非托管指针unmanagedPointer
2-Marshal.SizeOf不会提供非托管内存分配的大小
使用Marshal.Copy,可以将非托管内存的内容复制到托管字节数组,但需要知道需要将多少字节从非托管缓冲区移动到托管缓冲区。理想情况下,API应该提供此信息。调用引发的异常是正确的;该方法无法知道要传递给它的数组的长度,它只有一个指针 为此,获取数据的最简单方法是调用static,传递指向非托管数据的指针、要读取的索引和字节数,以及要封送数据的预分配字节缓冲区 至于获取数组的大小,如,对
Twain.GlobalLock(hImage)
的调用似乎(这里要非常小心)使用了分配给的内存,这意味着您可以通过p/Invoke层调用来获取大小
如果它不是通过调用
GlobalAlloc
分配的某个句柄,那么您需要了解Twain
模块是如何分配内存的,并使用适当的机制来确定IntPtr
指向的内存长度,为什么不能在调用中使用bmpptr
Gdip.SaveDIBAs
?这就是我今天修改的代码所做的,这个控件被用作一个活动的x控件,我们正在尝试摆脱图像的客户端存储。Gdip.SaveDIBAs正在将映像保存到本地存储,我希望能够将字节[]发送到服务器以创建映像。这段代码是我尝试的原型功能。好的,那么您只需要从非托管的bmpptr
转到byte[]
?结束状态,我想将非托管的bmpptr放到一个字节数组中,将其放到服务器上,然后通过获取字节[]重用Gdip.SaveDIBAs方法来创建映像服务器端并在那里创建同一个非托管指针。这真的不接近。任何一种半体面的Twain互操作库都可以让您从中获得HBITMAP。您可以从中创建图像并将()保存到任意流。这就是你现在通过pinvoking GDI+艰难地做的事情。如下:@Scruffy:需要通过其他方式获取数组的长度;请尝试GlobalSize
()谢谢您的帮助,我确实使用了MSDN文档作为入门参考。尽管我仍然不清楚从IntPtr中为字节[]的大小分配多少。@Scruffy:更新了答案以反映如何(可能)找到长度。根据上面的注释,我将从客户端向服务器发送字节数组,然后创建映像,而不是使用客户端存储。@Scruffy,那么同样的方法也应该适用。您的问题是确定缓冲区的大小。Marshal.SizeOf不起作用,您需要从twain API获取该信息。
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;
}