Marshal.PtrToStructure访问冲突
任何人都可以看到它为什么失败?如果我用“ref BITMAP lpvObject”替换“out IntPtr lpvObject”,我可以用它来工作。但我只是看不出代码的任何问题。Marshal.PtrToStructure访问冲突
using System;
using System.Runtime.InteropServices;
using System.Drawing;
namespace Program
{
class Core
{
[StructLayout(LayoutKind.Sequential)]
public struct BITMAP
{
public Int32 bmType;
public Int32 bmWidth;
public Int32 bmHeight;
public Int32 bmWidthBytes;
public UInt16 bmPlanes;
public UInt16 bmBitsPixel;
public IntPtr bmBits;
}
[DllImport("gdi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int GetObject (IntPtr hgdiobj, int cbBuffer, out IntPtr lpvObject);
static void Main(string[] args)
{
Bitmap TestBmp = new Bitmap (10, 10);
BITMAP BitmapStruct = new BITMAP();
IntPtr pBitmapStruct, pBitmapStructSave;
int Status;
pBitmapStructSave = pBitmapStruct = Marshal.AllocHGlobal (Marshal.SizeOf(BitmapStruct));
Status = GetObject (TestBmp.GetHbitmap(), Marshal.SizeOf (BitmapStruct), out pBitmapStruct);
Console.WriteLine ("\nBytes returned is " + Status + ", buffer address = " + pBitmapStruct);
try
{
BitmapStruct = (BITMAP) Marshal.PtrToStructure (pBitmapStruct, typeof(BITMAP));
}
catch (Exception Ex)
{
Console.WriteLine (Ex.Message);
}
Marshal.FreeHGlobal(pBitmapStructSave);
}
}
}
的输出是:
字节返回为32,缓冲器地址= 42949672960
未处理的异常:System.AccessViolationException:尝试读取或写入受保护存储器。这通常表明其他内存已损坏。
在System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr的PTR,类型structureType)
在Program.Core.Main(字串[] args)在d:\数据\项目\测试\测试\程序.cs:line 41
难道是因为您使用了错误的签名吗?
[DllImport(“gdi32.dll”)] static extern int GetObject(IntPtr hgdiobj,int cbBuffer,IntPtr lpvObject);
http://www.pinvoke.net/default.aspx/gdi32/GetObject.html
此外,出意味着,值需要在方法中被初始化,并且很可能不会发生,因为你已经有了lpvObject定义。
API规范声明了输出第三个参数:_Out_ LPVOID lpvObject。所以签名很好。程序输出表明out参数按照预期返回一个指针值。 – user118708
好的,谢谢。我删除了“出”,现在它正在工作。我必须重新阅读out关键字的使用方式。 – user118708
@ user118708看[示例用法](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145119(v = vs.85).aspx),您需要传入地址有效的缓冲区。我不知道它为什么在文档中标记为OUT,但它肯定需要一个通过的有效对象 –
'out IntPtr lpvObject' - >'IntPtr lpvObject' – PetSerAl
使用int GetObject(IntPtr hgdiobj,int cbBuffer,out BITMAP lpobj)。十分简单。 –
是的,它也适用于参考BITMAP,如我所述。这样做的麻烦是当函数返回一个空的第三个参数时需要额外的处理。最简单的解决方案仍然是将指针作为输出。无论如何,我需要知道IntPtr类型是一个隐式输出。我不会在一千年内猜出它。我也不会从搜索中找到它。 – user118708