我在C++中具有以下结构:(使用编译指示包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 Assistant的信任放错了位置吗?

编辑:

这是我用来往返IntPtr的代码。我知道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));
    }

最佳答案

我尚未深入研究该结构,但肯定看起来生成的签名是正确的。这些结构没有什么特别棘手的,并且所有类型都已适当匹配。

问题很可能是lppList参数的编码。您能否快速举例说明如何1)取回该数据和2)试图封送lppList的代码。

如果在原始结构上使用#pragma pack,也可能会出现问题。 PInvoke Interop Assistant不会尝试解释打包命令。您可能必须在结构上手动调整该设置。

编辑

一个问题可能是lpPhysicalPositionName和lpPhysicalCashUnit参数。尝试将它们切换为IntPtr vs. String并删除Marshal属性。

警告:我写了这个工具,所以我对它的可靠性有很大的偏见:)

09-27 23:41