我需要使用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确实是“最好的”(最简单/最快)的方式吗?
答案 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构造函数可以将其作为参数。