从 C++ DLL 返回的结构缺少数组数据中的第一个元素

Struct returned from C++ DLL missing first element in array data

我有一个 Unity5 程序,它使用通用结构 (smMsg) 将数据从 C++ DLL 发送到 C#。

该结构包含一个数组:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public float[] mtx; 

这个数组将被视为 4x4 矩阵,因此大小为 16。


程序运行,接收数据进入C#对应结构体;但是,似乎从我的数组中我每次 运行 程序时都缺少 first 元素(mtx[0])。似乎所有其他元素都向左移动,最后一个元素有一个额外的 0,保持它们所在的顺序。

我认为这是因为我使用的 UnmanagedType,但是其他消息来源告诉我 UnmanagedType.ByValArray 是正确的类型。

任何人都可以提供指导或线索来帮助解决这个问题吗?


复制数据的过程

C#:

// DLL Import
[DllImport(DLL_NAME, EntryPoint = "smCopy")] 
private static extern void smCopyData(IntPtr dest, IntPtr len); //const VOID *dest, SIZE_T len);

// Copying data logic
{
    //  allocate intptr to buffer
    var len = Marshal.SizeOf(typeof(smMsg));
    IntPtr msg_intptr = Marshal.AllocHGlobal(len); 

    try
    {
        //  Copy data
        smCopyData(msg_intptr, (IntPtr)(len));

        //  Set POINTER data to struct
        return_msg = (smMsg)Marshal.PtrToStructure(msg_intptr, typeof(smMsg));

    }
    finally
    {
        //  free unmanaged memory!
        Marshal.FreeHGlobal(msg_intptr);
    }
}

C++

// Function called via DLL
void DLL_API smCopy(const VOID *dest, SIZE_T len)
{
    CopyMemory((PVOID)(dest), (PVOID)(mapBuffer), len);
}

结构定义

我感兴趣的主要数据是float[] mtx

[StructLayout(LayoutKind.Sequential)]
public struct smMsg 
{
   public smHeader header;
   public smData data; 
}

[StructLayout(LayoutKind.Sequential)]
public struct smData
{
   // Event ID.
   public int evtId;
   public int status;

   // Floating point values. Actual data to be transmitted.
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
   public float[] mtx; 
}

[StructLayout(LayoutKind.Sequential)]
public struct smHeader
{
   public ushort chkSum;
   public char numWords;
   public char msgType;
}

更新 2/29

感谢@Zastai,我最终能够恢复丢失的元素。事实证明,我想使用 "byte" 作为数据类型而不是 char,因为 char 是 C# unicode 类型(简称)。

我最后做的是将我的 smHeader 更改为:

[StructLayout(LayoutKind.Sequential)]
public struct smHeader   
{
   public ushort chkSum; 

   public byte numWords;

   public byte msgType;
}

.. 这又将 smHeader 大小从 6 降低到 4,将 smMsg 结构大小设置为在 C# 和 C++ 中相等。

感谢@Zastai 的帮助。

事实证明,当在 C++ 中对结构使用 char 时,它在 C# 中的对应物是 byte。这解决了 C# 和 C++ 之间结构大小的差异。由于这个错误,C# 中的 smMsg 结构分配了比它需要的更多的内存。

问题已更新为新的 smHeader 定义。