将浮点数组编组到 C#

Posted

技术标签:

【中文标题】将浮点数组编组到 C#【英文标题】:Marshalling float Array to c# 【发布时间】:2015-05-22 14:27:54 【问题描述】:

我正在尝试将包含浮点数组的结构从 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# 中打印 data[] 时,我得到以下输出: 1.175494E-38 1.610935E-32 8.255635E-20

我做错了什么?

【问题讨论】:

【参考方案1】:

我不确定你为什么要做所有不安全的事情和指针操作。如果你正确定义了你的结构,它非常简单:

[StructLayout(LayoutKind.Sequential)]
public struct dataStruct

    [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)]
    public float[] data;
    public int otherStuff;

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

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

【讨论】:

【参考方案2】:

你必须使用正确的类型:

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 ;
        
    

不使用不安全的代码。

【讨论】:

谢谢。效果很好。也许你可以帮我最后一次,因为我的整个结构仍然没有正确编组:***.com/questions/30464437/…

以上是关于将浮点数组编组到 C#的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将浮点指针从 C 库传递到其 C# 包装器

在 C# 中“转换”浮点数为双精度值

为啥 SQL 浮点数与 C# 浮点数不同

格式为 00:00:00 的 iOS 数组字符串到格式为 00.00.00 的数组浮点型 Objective C

字节数组byte[]和整型,浮点型数据的转换——Java代码

C语言字符串类型转换为整型或浮点怎么做