Copy unmanaged data into managed array

不打扰是莪最后的温柔 提交于 2019-12-03 06:59:45

问题


I need to copy native (i.e. unmanaged) data (byte*) to managed byte array with C++/CLI (array).

I tried Marshal::Copy (data is pointed to by const void* data and is dataSize bytes)

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

This gives error C2665: none of the 16 overloads can convert all parameters. Then I tried

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

which produces error C2664: parameter 1 cannot be converted from "const void*" to "__w64 int".

So how can it be done and is Marshal::Copy indeed the "best" (simplest/fastest) way to do so?


回答1:


"IntPtr" is just a wrapper around a "void *". You shouldn't need the new syntax, just use of the explicit conversion operator.

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

Should work.




回答2:


As you've noted, Marshal::Copy (and .NET in general), is not const-safe.

However, the usual C and C++ functions are. You can write either:

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

or to avoid pinning:

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



回答3:


All these answers dance around the real misunderstanding in the original question.. The essential mistake made is that this code:

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

is incorrect.. you don't new (or gcnew) an IntPtr. Its a value type. One of the answers shows this, but it doesn't point out the original misunderstanding. The correct code can be expressed this way:

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

This confused me when I first started using these constructs also..

IntPtr is a C# struct.. a value type.




回答4:


The C++/CLI compiler is a bit obtuse about this. The formal definition of IntPtr is "native integer", it is not a pointer type. The C++ language however only allows conversion of void* to a pointer type. The CLI supports pointer types but there are very few framework methods that accept them. Marshal::Copy() doesn't. One of the three IntPtr constructors does.

You have to whack the compiler over the head with a cast or by using the IntPtr constructor. It is anybody's guess if this will still work on a 128-bit operating system, I'm not going to worry about it for a while.




回答5:


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

Pay attention to (void*) which type-casts from (const void*) so new IntPtr constructor can take it as argument.



来源:https://stackoverflow.com/questions/6403005/copy-unmanaged-data-into-managed-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!