在c#和c ++之间使用字符串编组结构数组。字符串是空的

时间:2017-02-09 04:26:53

标签: c# c++ arrays struct marshalling

我最困难的时候在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;

                }
            }

1 个答案:

答案 0 :(得分:0)

原来问题出现在C ++方面,并且所有的编组都是正确的。感谢小费汉斯。