Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 封送包含可变长度数组的C结构_C#_C_Arrays_Struct_Marshalling - Fatal编程技术网

C# 封送包含可变长度数组的C结构

C# 封送包含可变长度数组的C结构,c#,c,arrays,struct,marshalling,C#,C,Arrays,Struct,Marshalling,我想将带有可变长度数组的C结构封送回C#,但到目前为止,我没有比指向结构表示的指针和指向浮点的指针更好的了 非托管表示: typedef float smpl_t; typedef struct { uint_t length; /**< length of buffer */ smpl_t *data; /**< data vector of length ::fvec_t.length */ } fvec_t; 我想要的是一个.NET样式的数组,其

我想将带有可变长度数组的C结构封送回C#,但到目前为止,我没有比指向结构表示的指针和指向浮点的指针更好的了

非托管表示:

typedef float        smpl_t;

typedef struct {
  uint_t length;  /**< length of buffer */
  smpl_t *data;   /**< data vector of length ::fvec_t.length */
} fvec_t;
我想要的是一个.NET样式的数组,其中
数据
将是
float[]
,但是如果我将结构更改为下面的形式,我确实无法在上面的外部函数中获取托管类型的地址、大小或声明指向托管类型的指针

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

    public float[] data;
}
,不可能按原样封送变长数组,这是正确的还是仍然有办法实现这一点?

简短回答 不能将可变长度数组封送为数组,因为在不知道大小的情况下,互操作封送服务无法封送数组元素

但如果您知道尺寸,它将如下所示:

int arr[15]
您将能够像这样封送它:

[MarshalAs(UnmanagedType.LPArray, SizeConst=15)] int[] arr
如果你不知道数组的长度,这就是你想要的
您可以将其转换为intprt并处理inptr,但首先需要创建2个结构

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

    public int[] data;
}
另一个如下所示:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct fvec_t2{
    public uint whatever;
}
创建一个函数来初始化数组,如下所示

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

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

    return myInt;
}
实例化第二个结构

fvec_t2 instance1 = new fvec_t2();

instance1.whatever = instance.whatever
为fvec_t2结构动态分配空间,并为数据数组扩展空间

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(fvec_t2)) + Instance.data.Length);
将fvec_t2的现有字段值转移到ptr指向的内存空间

Marshal.StructureToPtr(instance1, ptr, true);
计算应位于fvec_t2末尾的数据数组字段的偏移量 结构

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

IntPtr address = new IntPtr(ptr.ToInt32() + offset);
将数据复制到ptr

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

bool success = dllfunction(ptr);

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

在上述情况下,我肯定会使用SizeParamIndex

[StructLayout(LayoutKind.Sequential)]
public struct fvec_t1
{
    uint length;
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] data;
}

祝你好运。

我读了,我说你不能那样做:)。如果你不喜欢我的answe,我可以删除它,如果我可以提前知道大小,那么我就不会问这个问题:-)你可以将它转换为intprt并处理inptr,同样,由于我上面提到的原因,你不能使用float[]数据。但我真的不明白你为什么不投票给我的答案:)@Aybe现在检查我的答案希望这会有帮助:dwy你为什么分配
Marshal.SizeOf(typeof(fvec_t2))+Instance.data.Length
int
type不是1字节的长度。通过将数组作为参数传递,可以很容易地做到这一点。你为什么不这么做?你为什么使用不安全的
?你能详细说明一下吗?问题是,当我指定MarshalAs.Struct时,调用可以工作,但返回的结构是垃圾(长度不正确),所以我猜它不能正常工作。因此,目前唯一有效的方法是返回struct指针并手动访问
数据中的项。关于不安全语句,我刚刚忘记删除它。不能将数组放在结构中,而让封送拆收器来完成这项工作。但是您可以将数组作为指针传递并对其进行封送处理。我会尝试一下,谢谢。不幸的是,
SizeParamIndex
仅适用于直接作为参数传递的数组,而不适用于结构中的数组。“这一定是,”皮达尔真的吗?这很不幸,我很惊讶。根据,在“声明原型”下,您可以在那里使用
SizeConst
Marshal.Copy(instance.data, 0, address, instance.data.Length);
bool success = dllfunction(ptr);

Marshal.FreeHGlobal(ptr);
ptr = IntPtr.Zero;
[StructLayout(LayoutKind.Sequential)]
public struct fvec_t1
{
    uint length;
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] float[] data;
}