C ++函数知道数组的大小并必须创建它。
C ++代码:
__declspec(dllexport) int getlog(int* &data)
{
data = new int[5];
for (int i = 0; i < 5; i++)
{
data[i] = i;
}
return 0;
}
和C#:
[DllImport(@"myDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int getlog(int[] data);
和
int[] arr = null;
getlog(arr);
我看到了,但没有帮助
在C#方面:
[DllImport(@"myDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int getlog([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out int[] data,
out int length);
在C ++方面:
#include <Objbase.h>
extern "C" __declspec(dllexport) int getlog(int** data, int * length)
{
*length = 5;
int sizeInBytes = sizeof(int) * (*length);
*data = static_cast<int*>(CoTaskMemAlloc(sizeInBytes ));
for (int i = 0; i < 5; i++)
{
(*data)[i] = i;
}
return 0;
}
CoTaskMemAlloc
一旦无法访问,CLR就会提供释放内存的功能。有关更多信息,请参见“使用Interop Marshaler进行内存管理”:
运行时始终使用该
CoTaskMemFree
方法释放内存。如果您正在使用的内存未与该CoTaskMemAlloc
方法一起分配,则必须使用IntPtr
并使用适当的方法手动释放内存。
上面的方法适用于.NET 4.0及更高版本。对于.NET 3.5,由于对非托管数组的有限支持,它失败了:
被控制的数组不能作为ref或out参数传递。同样,包含数组大小的参数必须按值传递(SizeParamIndex字段不能引用ref或out参数)
要克服此问题并在C#端获取数组,请使用以下签名:
[DllImport(@"MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int getlog(out IntPtr data, out int length);
当您需要IntPtr
数据时,可以将内容复制到托管阵列:
int length;
IntPtr data;
getlog(out data, out length);
int[] managedArr = new int[length];
Marshal.Copy(data, managedArr, 0, length);
同样,您可以处理这种数组的内容而无需应对。要使用此方法,请在项目设置中启用“允许不安全代码”:
int length;
IntPtr data;
getlog(out data, out length);
unsafe
{
int* intArray = (int*)data.ToPointer();
for (int i = 0; i < length; i++)
{
Console.WriteLine(intArray[i]);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句