编组浮点数组到c#

本文关键字:数组 | 更新日期: 2023-09-27 17:50:22

我试图封送一个结构体,其中包含一个浮点数组从c++ DLL到c#。

我用以下代码创建了c++ DLL:

//MarshalTest.h
namespace mTest{
    typedef struct {
        float data[3];
        int otherStuff;
    } dataStruct;
    extern "C" __declspec(dllexport) dataStruct getData();
}
//MarshalTest.cpp
#include "MarshallTest.h"
using namespace std;
namespace mTest{
    dataStruct getData(){
        dataStruct d = {{ 16, 2, 77 }, 5};
        return d;
    }
}
我使用以下代码使getData-Function在c#中可用:
public unsafe struct dataStruct{
    public fixed byte data[3];
    public int otherStuff;
    public unsafe float[] Data{
        get{
            fixed (byte* ptr = data){
                IntPtr ptr2 = (IntPtr)ptr;
                float[] array = new float[3];
                Marshal.Copy(ptr2, array, 0, 3);
                return array;
            }
        }
        set{
            fixed (byte* ptr = data){
                //not needed
            }
        }
    }
}
[DllImport("MarshallTest", CallingConvention = CallingConvention.Cdecl)]
private static extern dataStruct getData ();

在c#中打印数据[]时,我得到以下输出:1.175494 38吗1.610935 e-328.255635 e-20

我做错了什么?

编组浮点数组到c#

我不知道你为什么要做所有不安全的东西和指针操作。如果你正确地定义了你的结构,那就很简单了:

[StructLayout(LayoutKind.Sequential)]
public struct dataStruct
{
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)]
    public float[] data;
    public int otherStuff;
}

您只需要使用关于您的类型的一些附加信息指示互操作编组,然后您可以在不使用不安全结构和指针的情况下获得非托管数据。在c#中使用指针的理由非常非常少。

你的可能不工作,因为你使用byte[]数组作为第一个参数,所以当从非托管端复制数据时,你正在覆盖大量数据(也许你认为使用fixed将它们变成指针?)。类型必须匹配,以便结构匹配并正确复制数据。此外,由于c#会自动重新安排结构以最适合内存,因此您可能不会按照您的想法放置数据。这就是StructLayout在上面例子的顶部所做的,它告诉编译器保持结构的顺序定义。

必须使用正确的类型:

public unsafe struct dataStruct2
{
    public fixed float data[3];
    public int otherStuff;
    public unsafe float[] Data
    {
        get
        {
            fixed (float* ptr = data)
            {
                float[] array = new float[3];
                Marshal.Copy((IntPtr)ptr, array, 0, 3);
                return array;
            }
        }
    }
}

注意,对于小数组,您甚至可以使用:

public struct dataStruct
{
    public float data1;
    public float data2;
    public float data3;
    public int otherStuff;
    public float[] Data
    {
        get
        {
            return new[] { data1, data2, data3 };
        }
    }
}

不使用不安全代码