C # - преобразование любого небезопасного неуправляемого типа в управляемый тип без какого-либо нового выделения памяти - сохранение того же размера в памяти - PullRequest
0 голосов
/ 20 января 2019

Я хочу преобразовать массив ushort в короткий массив без выделения новой памяти в ядре C #.

Также преобразуйте любой тип, например, byte [], в short [] или наоборот - для преобразования необходимо сохранить одинаковый размер в памяти как для источника, так и для пункта назначения

В C был синтаксис "union", к которому тип можно ссылаться с помощью приведения типов - я не нашел никакого эквивалента для C # (который работает только для не примитивных типов).

Один из способов - написать код

ushort[] res = new ushort[1024 * 1024 * 1024];
short[] s = new short[1024 * 1024 * 1024];
Buffer.BlockCopy(s, 0, res, 0, s.Length * 2);

... но я не хочу выделять значение 's' - это слишком много памяти и может привести к утечке памяти.

Другая альтернатива, которую я использую, - это небезопасный режим.

код:

unsafe
{
    ushort[] res = new ushort[10241024]; // large allocating
    fixed (ushort* ss = &res[0])
    {
        IntPtr ps = (IntPtr)ss;
        short[] s0 = (short[])Marshal.PtrToStructure(ps, typeof(short[]));
    }
}

столкнуться с исключением.

Для этого объекта не определен конструктор без параметров. *1024*

...

в System.RuntimeTypeHandle.CreateInstance (тип RuntimeType, логическое значение publicOnly, логическое исключение wrapException, логическое значение & canBeCached, RuntimeMethodHandleInternal & ctor)

at System.RuntimeType.CreateInstanceSlow (логическое значение publicOnly, логическое значение wrapExceptions, логическое значение skipCheckThis, логическое значение fillCache)

в System.Runtime.InteropServices.Marshal.PtrToStructure (IntPtr ptr, Тип структурыType)

Как я могу в конечном итоге преобразовать этот большой массив в 1 Гбайт без необходимости выделять новую память?

Можно ли преобразовать тип массива из неуправляемого типа в управляемый тип?

Я предпочитаю использовать небезопасный режим, если это возможно.


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

Это код работает очень хорошо, если массивы имеют одинаковый размер - Есть новый вопрос - Как я могу решить это для не того же размера базового типа массива (то есть short [] vs byte [])?

Единственное, что я не могу преобразовать из короткого [] в байт [].

(Спасибо, какой-то блог в интернете: https://social.msdn.microsoft.com/Forums/vstudio/en-US/06ac44b0-30d8-44a1-86a4-1716dc431c62/how-to-convert-an-intptr-to-an-object-in-c?forum=clr)

Это работает на ядре C #, а также на C # .NET

Во-первых, создайте класс:

public static class MyConverter
{
    public static unsafe T GetInstance<T>(IntPtr pointer)
    {
        try
        {
            var fakeInstance = default(T);
            TypedReference typedReference = __makeref(fakeInstance);
            *(IntPtr*)(&typedReference) = pointer;
            T instance = (T) __refvalue(typedReference,T);
            return instance;
        }
        catch
        {
            return default(T);
        }
    }
}

и может использовать его в таком коде:

      ushort[] x = new ushort[1024];
      GCHandle handle1 = GCHandle.Alloc(x);
      IntPtr px = (IntPtr)handle1;
      x[0] = 1;
      x[1] = 2;
      x[2] = 3;
      short[] s = MyConverter.GetInstance<short[]>(px);

Это решение преобразует ushort [] в short [] без потери памяти.

Спасибо.

1 Ответ

0 голосов
/ 21 января 2019

Вы можете легко конвертировать так: (ushort[])(object)myShortArray. CLR позволяет это.

Это разрешено только для примитивных типов элементов массива одинакового размера.

В других случаях вы можете использовать Span для обработки памяти как другого типа.

Span<int> asInts = MemoryMarshal.Cast<byte, int>(asBytes);
...