将结构的元数据数组转换为Ptr

时间:2019-03-28 14:52:03

标签: c#

我正在从C#代码调用C库。我正在调用的函数将包含struct数组的struct作为参数:

    struct Example1Struct
    {
        char* a;
        uint16_t b;
        AnotherStruct* c; 
    }

c是一个指向AnotherStruct的指针的数组。

我的C#代码中的结构看起来像这样

public struct Example1Struct
    {
        public IntPtr StationName;//is char*
        public UInt16 IdCode;
        public IntPtr AnotherStruct; //array of struct  AnotherStruct
    }




public static IntPtr MarshalToPointer(object data)
    {
        Type valueType = data.GetType();
        IntPtr buf = IntPtr.Zero;

        if (valueType.IsArray)
        {
            if (data is char[])
            {
                var d = data as char[];
                buf = Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType()) * d.Length);
            }
            else if (data is char[,])
            {
                var d = data as char[,];
                buf = Marshal.AllocHGlobal(Marshal.SizeOf(d.GetType().GetElementType()) * d.Length);
            }
            else
            {
                buf = Marshal.AllocHGlobal(Marshal.SizeOf(data.GetType().GetElementType()) * count);

                long LongPtr = buf.ToInt64(); // Must work both on x86 and x64
                for (int I = 0; I < data.Lenght; I++)
                {
                    IntPtr RectPtr = new IntPtr(LongPtr);
                    Marshal.StructureToPtr(data[I], RectPtr, false); // You do not need to erase struct in this case
                    LongPtr += Marshal.SizeOf(typeof(Rect));
                }

            }

            return buf;
        }
        else
            buf = Marshal.AllocHGlobal(Marshal.SizeOf(data));
        Marshal.StructureToPtr(data, buf, false);
        return buf;
    }

我的问题是我无法在IEnumerable中将数据(是AnotherStruct的数组)投射到object []。所以我无法访问数据[I]并且没有数据。长度

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

通常,我建议使用MarshalAs属性,而不要编写手动编组代码。看起来像:

public struct Example1Struct
{
    public IntPtr StationName;//is char*
    public UInt16 IdCode;
    public IntPtr AnotherStruct; //array of struct  AnotherStruct
}

可能是:

public struct Example1Struct
{
    [MarshalAs(UnmanagedType.LPStr)]
    public string StationName;
    public UInt16 IdCode;
    [MarshalAs(UnmanagedType.LPArray)]
    public AnotherStruct[] OtherStructs;
}

当编组将其传递给非托管代码时,编组器应该为您做正确的事情。

答案 1 :(得分:0)

您可以像这样获得数组的长度:

if (data is Array a) 
    Console.WriteLine(a.Length);

c#中的数组始终从Array派生,因此可以将其强制转换为该数组。

但是如果可能的话,我建议使用Damien's answer