将非托管数据复制到托管阵列中

Jef*_*Son 18 c++-cli

我需要使用C++/CLI(数组)将本机(即非托管)数据(byte*)复制到托管字节数组.

我试过Marshal :: Copy(数据由const void*data指向,是dataSize字节)

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

这给出了错误C2665:16个重载中没有一个可以转换所有参数.然后我试了一下

System::Runtime::InteropServices::Marshal::Copy(new IntPtr(data), _Data, 0, dataSize);
Run Code Online (Sandbox Code Playgroud)

产生错误C2664:参数1无法从"const void*"转换为"__w64 int".

那怎么可能呢?Marshal :: Copy确实是"最好的"(最简单/最快)的方式吗?

Ben*_*igt 13

正如您所指出的那样Marshal::Copy(和.NET一般),不是const-safe.

但是,通常的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);
Run Code Online (Sandbox Code Playgroud)

或者避免钉扎:

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


Bra*_*etz 12

" IntPtr "只是"void*"的包装.您不应该使用新语法,只需使用显式转换运算符.

System::Runtime::InteropServices::Marshal::Copy( IntPtr( ( void * ) data ), _Data, 0, dataSize );
Run Code Online (Sandbox Code Playgroud)

应该管用.


小智 9

所有这些答案围绕着原始问题中的真正误解而跳舞.所犯的基本错误是这段代码:

System::Runtime::InteropServices::Marshal::Copy(new IntPtr(data), 
                                                _Data, 
                                                0, 
                                                dataSize)
Run Code Online (Sandbox Code Playgroud)

是不正确的..你不是新的(或gcnew)一个IntPtr.它是一种价值类型.其中一个答案显示了这一点,但它没有指出原来的误解.正确的代码可以这样表达:

System::Runtime::InteropServices::Marshal::Copy(IntPtr((void *)data), 
                                                _Data, 
                                                0, 
                                                dataSize)
Run Code Online (Sandbox Code Playgroud)

当我第一次开始使用这些结构时,这让我很困惑.

IntPtr是一个C#struct ..一个值类型.


Han*_*ant 8

C++/CLI编译器对此有点迟钝.IntPtr的正式定义是"本机整数",它不是指针类型.但是,C++语言只允许将void*转换为指针类型.CLI支持指针类型,但很少有框架方法接受它们.Marshal :: Copy()没有.三个IntPtr构造函数之一.

你必须使用强制转换或使用IntPtr构造函数来敲击编译器.任何人都猜测这是否仍然适用于128位操作系统,我暂时不会担心它.

  • +1"打击头编译器" (3认同)