【发布时间】:2020-07-06 12:13:12
【问题描述】:
我的 C++ 应用程序中有一个数组,我想使用它的指针从它创建一个 C# 数组委托而不复制。 所以我可以让它从 C# 到 C++ 工作,C++ 访问在 C# 中定义的同一个数组,但不能让它反向工作。
C#代码:
[DllImport("CppDll.dll",CallingConvention=CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPArray)]
public static extern int[] GetCppArray();
C++ 代码:
int test_data[5] = { 12,60,55,49,26 };
extern "C" __declspec(dllexport) int* GetCppArray()
{
return test_data;
}
在 C# 中使用:
int[] cpparray = NativeLib.GetCppArray();
我得到了这个错误:
System.Runtime.InteropServices.MarshalDirectiveException: '不能 marshal 'return value': 无效的托管/非托管类型组合。'
我知道我可以使用内存写入器通过数组指针地址直接写入 C++ 内存。
如果在参数中使用相同的 MarshalAs(UnmanagedType.LPArray) 并将 C# 数组传递给 c++,它可以工作,但为什么它在相反的操作中不起作用?
注意:我的数据量很大,我真的不能在这里使用任何副本。
【问题讨论】:
-
是.NET framework还是.NET core?
-
使用 .NET Framework,如果您不想复制,则必须 1) 从 GetCppArray 返回
IntPtr而不是int[]和 2) 使用unsafe关键字并强制转换返回 @ 987654329@asint*,有点像:stackoverflow.com/a/28279003/403671 如果你不想要unsafe代码,你将不得不以某种方式复制数组。 -
@SimonMourier 我不想使用不安全的
-
所以你必须以某种方式复制(使用 Array.Copy)。不能吃你的蛋糕。它被称为“托管”。
-
另一种选择是使用
C++\CLI。我更新了我的答案,向您展示了一个示例。没有数据复制,没有不安全,并且您使用C++\CLI包装器的方式与使用简单的C#数组的方式非常相似。