我在C ++中有以下结构:(使用pragma pack 1)
typedef struct _wfs_cdm_physicalcu
{
LPSTR lpPhysicalPositionName;
CHAR cUnitID[5];
ULONG ulInitialCount;
ULONG ulCount;
ULONG ulRejectCount;
ULONG ulMaximum;
USHORT usPStatus;
BOOL bHardwareSensor;
} WFSCDMPHCU, * LPWFSCDMPHCU;
typedef struct _wfs_cdm_cashunit
{
USHORT usNumber;
USHORT usType;
LPSTR lpszCashUnitName;
CHAR cUnitID[5];
CHAR cCurrencyID[3];
ULONG ulValues;
ULONG ulInitialCount;
ULONG ulCount;
ULONG ulRejectCount;
ULONG ulMinimum;
ULONG ulMaximum;
BOOL bAppLock;
USHORT usStatus;
USHORT usNumPhysicalCUs;
LPWFSCDMPHCU *lppPhysical;
} WFSCDMCASHUNIT, * LPWFSCDMCASHUNIT;
typedef struct _wfs_cdm_cu_info
{
USHORT usTellerID;
USHORT usCount;
LPWFSCDMCASHUNIT *lppList;
} WFSCDMCUINFO, * LPWFSCDMCUINFO;
P / Invoke Interop Assistant给出了以下输出:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)]
public struct WFSCDMPHCU {
/// LPSTR->CHAR*
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string lpPhysicalPositionName;
/// CHAR[5]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
public string cUnitID;
/// ULONG->unsigned int
public uint ulInitialCount;
/// ULONG->unsigned int
public uint ulCount;
/// ULONG->unsigned int
public uint ulRejectCount;
/// ULONG->unsigned int
public uint ulMaximum;
/// USHORT->unsigned short
public ushort usPStatus;
/// BOOL->int
public int bHardwareSensor;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet=System.Runtime.InteropServices.CharSet.Ansi, Pack = 1)]
public struct WFSCDMCASHUNIT {
/// USHORT->unsigned short
public ushort usNumber;
/// USHORT->unsigned short
public ushort usType;
/// LPSTR->CHAR*
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string lpszCashUnitName;
/// CHAR[5]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=5)]
public string cUnitID;
/// CHAR[3]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=3)]
public string cCurrencyID;
/// ULONG->unsigned int
public uint ulValues;
/// ULONG->unsigned int
public uint ulInitialCount;
/// ULONG->unsigned int
public uint ulCount;
/// ULONG->unsigned int
public uint ulRejectCount;
/// ULONG->unsigned int
public uint ulMinimum;
/// ULONG->unsigned int
public uint ulMaximum;
/// BOOL->int
public int bAppLock;
/// USHORT->unsigned short
public ushort usStatus;
/// USHORT->unsigned short
public ushort usNumPhysicalCUs;
/// LPWFSCDMPHCU*
public System.IntPtr lppPhysical;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
public struct WFSCDMCUINFO {
/// USHORT->unsigned short
public ushort usTellerID;
/// USHORT->unsigned short
public ushort usCount;
/// LPWFSCDMCASHUNIT*
public System.IntPtr lppList;
}
但是,当使用Marshal.PtrToStruct(例如,在WFSCDMCUINFO.lppList上)时,我会得到垃圾;当使用Visual Studio查看内存时,我在另一个内存条目中看到了实际内容(本身不是lppList)。
这些转换是否正确?我对P / Invoke Interop助手的信任错位了吗?
编辑:
这是我用来与IntPtr进行Marshal的代码。我知道Thread的想法很糟糕,但我稍后会谈到......
public static IntPtr GetIntPtr(this object obj) {
try {
var handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
var thread = new Thread(() => {
Thread.Sleep(20000);
handle.Free();
});
thread.Start();
return handle.AddrOfPinnedObject();
} catch (ArgumentException) {
var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
}
public static T FromIntPtr<T>(this IntPtr ptr) {
if (ptr == IntPtr.Zero)
return default(T);
return (T) Marshal.PtrToStructure(ptr, typeof (T));
}
答案 0 :(得分:3)
我没有对结构进行深入研究,但看起来生成的签名肯定是正确的。在这些结构中没有什么特别棘手的,所有类型都适当匹配。
问题可能是lppList参数的编组问题。您能否快速了解1)如何获取此数据以及2)尝试编组lppList的代码。
如果在原始结构上使用了#pragma pack,也可能会出现问题。 PInvoke Interop Assistant不会尝试解释pack命令。您可能必须手动调整结构上的该设置。
修改强>
一个问题可能是lpPhysicalPositionName和lpPhysicalCashUnit参数。尝试将它们切换到IntPtr vs. String并删除Marshal属性。
警告:我写了这个工具,所以我对它的可靠性有很大的偏见:)