Копировать неуправляемые данные в управляемый массив - PullRequest
18 голосов
/ 19 июня 2011

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

Я пробовал Marshal :: Copy (на данные указывает const void *data и dataSize bytes)

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".

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

Ответы [ 5 ]

13 голосов
/ 20 июня 2011

Как вы заметили, Marshal::Copy (и .NET в целом) не является const -безопасным.

Однако обычные функции C и 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];
12 голосов
/ 19 июня 2011

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

9 голосов
/ 09 июня 2012

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

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

неверен.,Это тип значения.Один из ответов показывает это, но не указывает на первоначальное недоразумение.Правильный код можно выразить так:

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

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

IntPtr - это структура C # .. тип значения.

8 голосов
/ 19 июня 2011

Компилятор C ++ / CLI немного туповат по этому поводу. Формальное определение IntPtr - «родное целое число», это не тип указателя. Однако язык C ++ допускает только преобразование void * в тип указателя. CLI поддерживает типы указателей, но существует очень мало каркасных методов, которые их принимают. Marshal :: Copy () нет. Один из трех конструкторов IntPtr делает.

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

1 голос
/ 29 декабря 2011

System :: :: среды выполнения InteropServices :: Marshal :: Copy (новый IntPtr ((void *) data), _Data, 0, dataSize);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...