Pregunta Copie datos no administrados en una matriz administrada


Necesito copiar datos nativos (es decir, no administrados) (byte *) a la matriz de bytes administrados con C ++ / CLI (matriz).

Probé Marshal :: Copy (los datos están apuntados por los datos de const void * y son dataSize bytes)

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

Esto da el error C2665: ninguna de las 16 sobrecargas puede convertir todos los parámetros. Entonces probé

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

que produce el error C2664: el parámetro 1 no se puede convertir de "const void *" a "__w64 int".

Entonces, ¿cómo se puede hacer y es Marshal :: Copiar de hecho la "mejor" (más simple / más rápida) forma de hacerlo?


17
2018-06-19 14:34


origen


Respuestas:


"IntPtr"es solo una envoltura alrededor de un" vacío * ". No debería necesitar la nueva sintaxis, solo el uso del operador de conversión explícito.

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

Deberia trabajar.


12
2018-06-19 14:57



Como habrás notado, Marshal::Copy (y .NET en general), no es const-seguro.

Sin embargo, las funciones habituales de C y C ++ sí lo son. Puedes escribir:

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

o para evitar fijar:

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

12
2018-06-20 11:22



El compilador C ++ / CLI es un poco obtuso al respecto. La definición formal de IntPtr es "entero nativo", no es un tipo de puntero. Sin embargo, el lenguaje C ++ solo permite la conversión de void * a un tipo de puntero. La CLI admite tipos de punteros pero hay muy pocos métodos de marcos que los acepten. Marshal :: Copy () no. Uno de los tres constructores de IntPtr lo hace.

Tienes que golpear el compilador sobre la cabeza con un molde o usando el constructor IntPtr. Nadie sabe si esto funcionará en un sistema operativo de 128 bits, no me voy a preocupar por un tiempo.


8
2018-06-19 16:14



Todas estas respuestas bailan alrededor del verdadero malentendido en la pregunta original. El error esencial cometido es que este código:

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

es incorrecto ... usted no es nuevo (ni conoce) un IntPtr. Es un tipo de valor. Una de las respuestas muestra esto, pero no señala el malentendido original. El código correcto se puede expresar de esta manera:

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

Esto me confundió cuando comencé a usar estos constructos también ...

IntPtr es una estructura C # .. un tipo de valor.


8
2018-06-09 04:35



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

Presta atención a (vacío*) cual type-cast de (const void *) así que el nuevo constructor de IntPtr puede tomarlo como argumento.


1
2017-12-29 17:58