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

时间:2011-06-19 14:34:19

标签: 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);

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

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

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

那么怎么做呢?Marshal :: Copy确实是“最好的”(最简单/最快)的方式吗?

5 个答案:

答案 0 :(得分:13)

正如您所指出的那样,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];

答案 1 :(得分:12)

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

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

应该工作。

答案 2 :(得分:9)

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

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是一个C#struct ..一个值类型。

答案 3 :(得分:8)

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

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

答案 4 :(得分:1)

  

系统::运行:: InteropServices ::元帅:复制(新   IntPtr((void *)data),_ Data,0,dataSize);

注意(void *),其中类型转换自(const void *),因此新的IntPtr构造函数可以将其作为参数。