C# - 从指针创建托管数组

时间:2009-12-16 17:17:17

标签: arrays pointers unmanaged managed

我正在尝试从一个字节数组创建一个双重托管数组。我目前有问题,但我想优化。以下是我想要使用的一些代码:

private unsafe static double[] _Get_Doubles(byte[] _raw_data)
{
    double[] ret;
    fixed (byte* _pd = _raw_data)
    {
        double* _pret = (double*)_pd;
        ret = (double[])*_pret; //FAILURE
    }
}

请让我知道如何应对这些问题。

-Aaron

2 个答案:

答案 0 :(得分:3)

关于您发布的代码需要注意的一个关键事项是,无法知道返回值指向了多少项,托管数组需要知道它有多大。您可以返回double*或创建new double[XXX]并复制值或甚至(如果计数不变)创建struct成员public fixed double _data[2];并投射原始数据到那种类型。

答案 1 :(得分:2)

刚才,我认为stackalloc是正确的方式,但它失败了。最重要的是,我现在知道它注定要失败。没有办法做我想做的事。

通过重述问题可以看出这一点:

如何围绕'不安全'数组创建托管数组?

由于托管数组具有头信息(因为它是围绕内存块的类),因此内存中需要的空间比数组本身多。所以,答案是:

在数据本身之前(和/或之后?取决于托管数组存储在内存中的方式)分配空间,并将托管信息(长度,(等等))放在“不安全”数组周围。

这是不容易实现的,因为要保证阵列周围的数据足够充足。在我的特定示例中,可能有足够的空间,因为传递托管的byte []意味着数据周围有数据,但断言相同的数据适用于托管的double []最多是可疑的,但大多数可能是错误的,并且更改数据以使其适合托管的double []是邪恶的。

[编辑]

看起来Marshal.Copy是这里的方式。创建一个新数组并让Marshal复制它们(希望他会比我更快,或者可能在以后某个时候,他会更快):

var ret = new double[_raw_data.Length / sizeof(double)];
System.Runtime.InteropServices.Marshal.Copy(new System.IntPtr(_pret), ret, 0, ret.Length);