Подтвердить что ты не робот

Копирование неуправляемых данных в управляемый массив

Мне нужно скопировать собственные (т.е. неуправляемые) данные (byte *) в управляемый массив байтов с С++/CLI (массив).

Я попробовал Marshal:: Copy (данные указываются данными const void * и являются байтами dataSize)

array<byte>^ _Data=gcnew array<byte>(dataSize);
System::Runtime::InteropServices::Marshal::Copy((byte*)data, _Data, 0, dataSize);

Это дает ошибку C2665: ни одна из 16 перегрузок не может преобразовать все параметры. Затем я попробовал

System::Runtime::InteropServices::Marshal::Copy(new IntPtr(data), _Data, 0, dataSize);

который вызывает ошибку C2664: параметр 1 не может быть преобразован из "const void *" в "__w64 int".

Итак, как это можно сделать и есть Маршал:: Копировать действительно самый лучший (самый простой/быстрый) способ сделать это?

4b9b3361

Ответ 1

" IntPtr" всего лишь обертка вокруг "void *". Вам не нужен новый синтаксис, просто используйте явный оператор преобразования.

System::Runtime::InteropServices::Marshal::Copy( IntPtr( ( void * ) data ), _Data, 0, dataSize );

Должен работать.

Ответ 2

Как вы уже отметили, Marshal::Copy (и .NET в целом), не const -safe.

Однако обычные функции C и С++. Вы можете написать либо:

array<byte>^ data_array =gcnew array<byte>(dataSize);
pin_ptr<byte> data_array_start = &data_array[0];
memcpy(data_array_start, data, dataSize);

или избежать фиксации:

array<byte>^ data_array =gcnew array<byte>(dataSize);
for( int i = 0; i < data_array->Length; ++i )
    data_array[i] = data[i];

Ответ 3

Компилятор С++/CLI немного тупой об этом. Формальное определение IntPtr - это "собственное целое число", это не тип указателя. Однако язык С++ допускает преобразование void * в тип указателя. CLI поддерживает типы указателей, но их очень мало. Маршал:: Копировать() нет. Один из трех конструкторов IntPtr делает.

Вы должны ударить компилятор над головой приложением или с помощью конструктора IntPtr. Кто-нибудь догадывается, будет ли это работать на 128-битной операционной системе, я не буду беспокоиться об этом какое-то время.

Ответ 4

Все эти ответы танцуют вокруг настоящего недоразумения в оригинальном вопросе. Существенная ошибка заключается в том, что этот код:

System::Runtime::InteropServices::Marshal::Copy(new IntPtr(data), 
                                                _Data, 
                                                0, 
                                                dataSize)

неверно.. вы не новый (или gcnew) IntPtr. Его тип значения. Один из ответов показывает это, но он не указывает на первоначальное недоразумение. Правильный код может быть выражен следующим образом:

System::Runtime::InteropServices::Marshal::Copy(IntPtr((void *)data), 
                                                _Data, 
                                                0, 
                                                dataSize)

Это смутило меня, когда я впервые начал использовать эти конструкции.

IntPtr - это С# struct.. тип значения.

Ответ 5

Система:: Время воспроизведения:: InteropServices:: Marshal:: Copy (новый IntPtr ((void *)), _Data, 0, dataSize);

Обратите внимание на (void *), который выводит тип из (const void *), поэтому новый конструктор IntPtr может принимать его как аргумент.