2017-02-09 29 views
0

我在C#和C++之间编排这个结构最困难。 是什么让它很难排除故障是有些字符串填充数据(跆拳道),但大多数时间他们不是。使用c#和C++之间的字符串封装结构数组。字符串是空的

我试着发送一个结构数组以及一个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

'Pack = 1'不能正确,并给结构错误的大小。删除它。将C++代码中的'sizeof(FS_LMON_STATUS)'的值与C#代码中的'Marshal.SizeOf(FS_LMON_STATUS)'的值进行比较以进行仔细检查。 –

+0

我忘了提及,在C++方面,包被设置:#pragma pack(push,1),我编辑了上面的代码来显示。我将开始尝试在C++端挖掘结构的大小。 – Snipe3000

回答

0

原来,问题是在C++侧和所有的编组的东西是正确的。感谢提示汉斯。