名帅包含一个可变长度数组C结构 [英] Marshal a C struct containing a variable length array

查看:97
本文介绍了名帅包含一个可变长度数组C结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想名帅具有可变长度数组C结构回C#但到目前为止,我不能得到什么比一个指针到结构重新presentation和一个指向浮动更好。

I would like to marshal a C struct with a variable-length array back to C# but so far I can't get anything better than a pointer-to-struct representation and a pointer to float.

非网管重新presentation:

Unmanaged representation:

typedef float        smpl_t;

typedef struct {
  uint_t length;  /**< length of buffer */
  smpl_t *data;   /**< data vector of length ::fvec_t.length */
} fvec_t;

托管再presentation:

Managed representation:

[StructLayout(LayoutKind.Sequential)]
public unsafe struct fvec_t1
{
    public uint length;

    public float* data;
}

[DllImport("libaubio-4.dll", EntryPoint = "new_fvec", PreserveSig = true, CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe fvec_t1* new_fvec1(uint length);

我想是有一个.NET风格数组,其中数据浮动[] ,但如果我做了结构改变为下面的表格我得到的无法承担的地址,获取的大小,或宣布一个指向上方的外部函数托管类型

What I would like is to have a .NET style array, where data would be float[] but if I do change the struct to the form below I do get Cannot take the address of, get the size of, or declare a pointer to a managed type in the external function above.

[StructLayout(LayoutKind.Sequential)]
public unsafe struct fvec_t1
{
    public uint length;

    public float[] data;
}

显然的,以一个有编组回原样的可变长度数组它是不可能的,这是正确的或者是它还有一种方式来实现这一目标?

Apparently, it is not possible to a have a variable-length array marshalled back as-is, is this correct or is it there still a way to achieve this ?

推荐答案

简短回答
你不能封送可变长度数组的数组,因为如果不知道大小,互操作编组服务不能封送数组元素

short answer you can't marshal variable length array as an array , because Without knowing the size, the interop marshalling service cannot marshal the array elements

但如果你知道它的大小将是象下面这样:

but if you know the size it will be like below:

int arr[15]

您将能够名帅这样的:

[MarshalAs(UnmanagedType.LPArray, SizeConst=15)] int[] arr

如果你不知道数组的长度,这是你想要什么
   你可以将其转换为intprt和处理inptr但首先你需要创建2结构

if you don't know the length of the array and this is what you want you can convert it to intprt and deal with inptr but first you need to create 2 structs

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct fvec_t1
{
    public uint whatever;

    public int[] data;
}

另外一个象下面这样:

the other one like below:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct fvec_t2{
    public uint whatever;
}

创建一个函数来初始化数组像下面

create a function to initialize the array like below

private static int[] ReturnIntArray()
{
    int [] myInt = new int[30];

    for (int i = 0; i < myInt.length; i++)
    {
        myInt[i] = i + 1;
    }

    return myInt;
}

实例化的第一个结构

instantiate the first struct

fvec_t1 instance = new fvec_t1();
instance.whatever=10;
instance.data= ReturnIntArray();

实例第二结构

fvec_t2 instance1 = new fvec_t2();

instance1.whatever = instance.whatever

动态与数据阵列

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(fvec_t2)) + Instance.data.Length);

由ptr

Marshal.StructureToPtr(instance1, ptr, true);

计算数据阵列字段的偏移,这应是在一个fvec_t2的端
结构

Calculate the offset of data array field which should be at the end of an fvec_t2 struct

int offset = Marshal.SizeOf(typeof(fvec_t2));

根据获取的数据数组字段的内存地址的偏移量。

get memory address of data array field based on the offset.

IntPtr address = new IntPtr(ptr.ToInt32() + offset);

将数据复制到PTR

copy data to ptr

Marshal.Copy(instance.data, 0, address, instance.data.Length);

做好通话

bool success = dllfunction(ptr);

Marshal.FreeHGlobal(ptr);
ptr = IntPtr.Zero;

这篇关于名帅包含一个可变长度数组C结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆