用 c# 和 c++ 之间的字符串封送结构数组。字符串为空

Marshaling Struct Array with Strings Between c# and c++. Strings are empty

我在 C# 和 C++ 之间封送此结构时遇到了最困难的时间。 使故障排除变得非常困难的是,有时字符串中填充了数据 (wtf),但大多数时候它们不是。

我试过发送一个结构数组和一个 IntPtr,但结果是相似的,结构中的字符串几乎总是空的,我无法弄清楚我做错了什么编组。代码贴在下面。任何帮助将不胜感激。

编辑*** 事实证明问题出在 C++ 方面,所有编组的内容都是正确的。感谢提示汉斯。 ***

C++:

#pragma pack (push, 1)
typedef struct
{
    char FirmwareVers[FS_MAX_FIRMWARE_VER];
    char SerialNum[FS_MAX_SERIAL_NUM];
    char HardwareVers[FS_MAX_HW_VER];
    ULONG StatusFlags;
    int LMIndex; 
} FS_LMON_STATUS, *PFS_LMON_STATUS;


DllExport int _stdcall FS_GetLMs(PFS_LMON_STATUS pLaunchMonInfo, int MaxLaunchMons, int *pNumLaunchMons)
{
  int Cnt;
  FS_LMON_STATUS LMStatus;

    if(!g_IsInitalized)
        return FS_NOT_INITALIZED;

    *pNumLaunchMons = 0;

    if(MaxLaunchMons == 0)
        return FS_ERROR;

    for(Cnt = 0; Cnt < MAX_LM_CONNECTIONS; Cnt++)
    {
        if(g_CreatedClasses.pLMList->GetLMStatus(Cnt, &LMStatus) != FS_SUCCESS)
            continue;

        if(LMStatus.LMIndex != INVALID_LM_INDEX)
        {
            memcpy(pLaunchMonInfo, &LMStatus, sizeof(LMStatus));
            pLaunchMonInfo++;
            (*pNumLaunchMons)++;
            MaxLaunchMons--;

            if(MaxLaunchMons == 0)
            {
                return FS_SUCCESS;
            }
        } 
    }
    return FS_SUCCESS;
}

C#:

        [DllImport("FSADLL", SetLastError = false)]
        private static extern int FS_GetLMs([Out] IntPtr pLaunchMonInfo, int MaxLaunchMons, ref int pNumLaunchMons);


        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] //, Size = 38)]
        public struct FS_LMON_STATUS
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FS_MAX_FIRMWARE_VER)] //10 bytes
            public string FirmwareVers;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FS_MAX_SERIAL_NUM)] // 15 bytes
            public string SerialNum;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FS_MAX_HW_VER)] // 5 bytes
            public string HardwareVers;

            public uint StatusFlags; //4 bytes
            public int LMIndex;     // identifies which index //4 bytes
        }


            const int max_launch_monitors = 8;
            FS_LMON_STATUS[] dev_info =  new FS_LMON_STATUS[max_launch_monitors];
            int num_launch_monitors = 0;

            IntPtr pAddr = Marshal.AllocHGlobal(max_launch_monitors * Marshal.SizeOf(typeof(FS_LMON_STATUS)));
            Marshal.StructureToPtr(dev_info, pAddr, false);

            int result = FS_GetLMs(pAddr, max_launch_monitors, ref num_launch_monitors);
            UnityEngine.Debug.Log("Result of FS_GetLMs: " + result);

            FS_LMON_STATUS[] device_info = new FS_LMON_STATUS[max_launch_monitors];

            //Marshal.Copy(pAddr, device_info, (int)0, num_launch_monitors * (int)Marshal.SizeOf(typeof(FS_LMON_STATUS)));
            //Marshal.ReadIntPtr(pAddr, 0);
            //device_info = (FS_LMON_STATUS[]) Marshal.PtrToStructure(Marshal.AllocHGlobal(max_launch_monitors * Marshal.SizeOf(typeof(FS_LMON_STATUS[]))), typeof(FS_LMON_STATUS[]));

            if (num_launch_monitors > 0)
                UnityEngine.Debug.Log("GC2 Device Found.");
            else // If there is no devices found, remove the previous device from the holder variable 
                GC2Device = null;

            for (int i = 0; i < num_launch_monitors; i++)
            {
                device_info[i] = (FS_LMON_STATUS)Marshal.PtrToStructure(pAddr, typeof(FS_LMON_STATUS));
                pAddr = new IntPtr(Marshal.SizeOf(typeof(FS_LMON_STATUS)) + pAddr.ToInt64());
            }

            //*** There will only ever be 1 device in the list until the old SDK is fixed ***
            for (int lm_index = 0; lm_index < num_launch_monitors; lm_index++)
            {
                if (device_info[lm_index].StatusFlags != LM_STATUS_DISCONNECTED)
                {

                    UnityEngine.Debug.Log("device_info.SerialNum: " + device_info[lm_index].SerialNum);


                    //assign each LM to a LM data structure
                    LaunchMonitor logical_device = new LaunchMonitor(inst);
                    logical_device.mLaunchMonitorType = LaunchMonitorType.LAUNCH_MONITOR_TYPE_GC2;
                    logical_device.mConnectionType = ConnectionType.USB_CONNECTION;


                    IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(device_info[lm_index]));
                    Marshal.StructureToPtr(device_info[lm_index], pnt, false);
                    //Marshal.Copy(device_info[lm_index], dv_info, 0, (uint)Marshal.SizeOf(typeof(FS_LMON_STATUS)));

                    logical_device.mConnectionToken = pnt;
                    //GC2Devices.Add(logical_device);

                    logical_device.Serial = logical_device.GetSerialNumber();
                    GC2Device = logical_device;

                }
            }

事实证明问题出在 C++ 端,所有封送处理都是正确的。感谢汉斯的提示。