Копирование неуправляемых данных в управляемый массив
Мне нужно скопировать собственные (т.е. неуправляемые) данные (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".
Итак, как это можно сделать и есть Маршал:: Копировать действительно самый лучший (самый простой/быстрый) способ сделать это?
Ответы
Ответ 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 может принимать его как аргумент.