C # - Создать управляемый массив из указателя - PullRequest
7 голосов
/ 16 декабря 2009

Я пытаюсь создать управляемый массив значений типа double из массива байтов. У меня проблема с работой в данный момент, но я хотел оптимизировать. Вот код, над которым я бы хотел поработать:

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 ]

3 голосов
/ 16 декабря 2009

Одна из ключевых вещей, которую следует заметить в коде, который вы опубликовали, заключается в том, что нет способа узнать, сколько элементов указано возвращаемым значением, а управляемый массив должен знать, насколько он большой. Вы можете вернуть double* или создать new double[XXX] и скопировать значения или даже (если счет постоянный) создать struct с членом public fixed double _data[2]; и привести необработанные данные к этому типу.

2 голосов
/ 01 декабря 2010

Только сейчас я подумал, что stackalloc будет верным путем, но он терпит неудачу. Самое главное, теперь я знаю, что оно обречено на провал. Нет способа сделать то, что я хочу.

Это можно увидеть, повторив вопрос:

Как мне создать управляемый массив вокруг «небезопасного» массива?

Поскольку управляемый массив содержит информацию заголовка (потому что это класс вокруг куска памяти), ему требуется больше места в памяти, чем сам массив. Итак, ответ:

Выделите пространство до (и / или после? В зависимости от способа хранения управляемых массивов в памяти) самого массива и поместите управляемую информацию (длину, (и так далее)) вокруг массива 'unsafe'.

Это не легко возможно, потому что гарантировать, что вокруг массива достаточно данных, в лучшем случае шатко. В моем конкретном примере для этого может быть достаточно места, потому что передается управляемый байт [], что означает наличие данных вокруг массива, но утверждение о том, что те же данные подходят для управляемого двойного [], в лучшем случае сомнительно, но большинство скорее всего ошибочные, и изменение данных, чтобы сделать их подходящими для управляемого double [], является гнусным.

[РЕДАКТИРОВАТЬ]

Похоже, Marshal.Copy это путь сюда. Создайте новый массив и позвольте маршалу скопировать их (в надежде, что он будет быстрее меня или что, возможно, позже он будет быстрее):

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