64位中PRINT_NOTIFY_INFO_DATA这个Structure该怎么定义
昨天发了个贴没人理我,今天把问题再深入一些再发:)
先说明一下问题,PRINT_NOTIFY_INFO_DATA这个Structure在32位下OK,但是到了64位下获取到的东西是错误的,所以我觉得问题就出在这里了,下面是我目前的定义方法。
- VB.NET code
<StructLayout(LayoutKind.Sequential)> _ Private Class PrinterNotifyInfoData Public wType As Int16 Public wField As Int16 Public dwReserved As Int32 Public dwId As Int32 Public cbBuff As Int32 Public pBuff As Int32 End Class
请高人指点64位中的定义方法,C# VB都行,谢谢。
P.S.昨天贴的地址,没人回结贴都没法结。
http://topic.csdn.net/u/20120718/11/4031252f-3876-47eb-a8f7-b4676c8c641b.html
[解决办法]
拿一段简单的C++代码测试了一下PRINTER_NOTIFY_INFO_DATA结构:
总的来说,为了内存对齐,在Id和cbBuf之后有一段内存是留空了。
可以考虑Id和cbBuf字段用IntPtr来保证对齐,而使用属性通过位运算来读取/设置这些值。
[解决办法]
没有64位系统,没法测试,但你上面的定义肯定不对,字节对齐不是通过修改数据类型来实现的,那样做不出错的话,我叫他爷。C++里面默认是8字节对齐的,也就是#pragma pack (8),而C#里面也是,所以字节对齐是不会有不同的,除非C++里面有特殊指定。
[解决办法]
- C# code
typedef struct _PRINTER_NOTIFY_INFO_DATA { WORD Type; WORD Field; DWORD Reserved; DWORD Id; union { DWORD adwData[2]; struct { DWORD cbBuf; LPVOID pBuf; } Data; } NotifyData; } PRINTER_NOTIFY_INFO_DATA, *PPRINTER_NOTIFY_INFO_DATA;
[解决办法]
Codeplex上的一个项目也有过同样的问题,解决方案来自 不存在的网站
代码如下:
- C# code
[StructLayout(LayoutKind.Sequential)]public struct PRINTER_NOTIFY_INFO_DATA_DATA{ public uint cbBuf; public IntPtr pBuf;}[StructLayout(LayoutKind.Explicit)]public struct PRINTER_NOTIFY_INFO_DATA_UNION{ [FieldOffset(0)] private uint adwData0; [FieldOffset(4)] private uint adwData1; [FieldOffset(0)] public PRINTER_NOTIFY_INFO_DATA_DATA Data; public uint[] adwData { get { return new uint[] { this.adwData0, this.adwData1 }; } }}[StructLayout(LayoutKind.Sequential)]public struct PRINTER_NOTIFY_INFO_DATA{ public ushort Type; public ushort Field; public uint Reserved; public uint Id; public PRINTER_NOTIFY_INFO_DATA_UNION NotifyData;}
[解决办法]
64位下,adwData0和cbBuf应当具有相同值,adwData1的值不能由Data取到,因为pBuf之前有4字节被空置以对齐。
[解决办法]
PRINTER_NOTIFY_INFO的代码也是有的,出处同上
- C# code
[StructLayout(LayoutKind.Sequential)]public struct PRINTER_NOTIFY_INFO{ public uint Version; public uint Flags; public uint Count; [MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] public PRINTER_NOTIFY_INFO_DATA[] aData;}