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

本文关键字:DLL 返回 C++ 结构 元素 第一个 数据 数组 | 更新日期: 2023-09-27 18:36:22

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

该结构包含一个数组:

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

该数组应被视为 4x4 矩阵,因此常量大小为 16。


该程序工作,将数据接收到 C# 对应结构中;但是,每次运行程序时,似乎从我的数组中我都缺少第一个元素 (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,我最终能够恢复丢失的元素。事实证明,我想使用"字节"而不是 char 作为数据类型,因为 char 是 C# unicode 类型(短)。

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

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

.. 这反过来又将 smHeader 大小从 6 降低到 4,在 C# 和 C++ 方面设置 smMsg 结构大小相等。

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

感谢@Zastai帮了一吨忙。

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

该问题已使用新的 smHeader 定义进行更新。