当C#调用c ++函数时,是否可以在被调用的c ++函数中初始化数组并返回C#?

莫森

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章