如何将数组从C#传递给非托管DLL作为long []并获取值?

时间:2016-07-27 14:09:27

标签: c# dll marshalling

我有一个需要在非托管C DLL中调用函数的C#应用​​程序。我有它使用各种功能,所以设置似乎都很好。我能够将ref short传递给其中一个函数,它会更新变量中的值。但是,我遇到了一些使用long []作为输入的不同函数的问题,并且应该更新它以保存关于图像的一堆值。这是函数在.h文件中的样子:

short GetImage (
 short nIndex,            
 long  arrImageParam []
 );

以下是我们的C#代码在添加函数时的样子:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate short GetImage(short nIndex, int [] arrImageParam);

我正在调用这样的函数:

var arrImageParam = new int [20];
short b = GetImage.Invoke(1, arrImageParam);

这不起作用 - 当我尝试在Visual Studio中查看数组中的值时,我收到消息“无法读取内存”。我认为这是因为我们没有正确编组。

我们也试过这样的功能(使用“ref”):

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate short GetImage(short nIndex, ref int [] arrImageParam);

用ref输入调用它:

short c = GetImage.Invoke(1, ref arrImageParam);

给出错误:

FatalExecutionEngineError' - “附加信息:运行时遇到了致命错误。错误的地址是0x72cfe248,在线程0xf4c上。错误代码是0xc0000005。”

我们也在下面尝试了这个,但它似乎也没有正常工作 - 它将输出数组设置为2的长度并且似乎没有任何实际值

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate short GetImage(short nIndex, ref IntPtr arrImageParam);

-

      int[] array2 = new int[20];
      int size = array2.Length;
      for (int i = 0; i < array2.Length; i++)
      {
          array2[i] = i;              
      }
      IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(size)
         * array2.Length);
      Marshal.Copy(array2, 0, buffer, array2.Length);

      short c = GetImage.Invoke(1, ref buffer);

       int[] arrayRes = new int[size];
       Marshal.Copy(buffer, arrayRes, 0, size);
       Marshal.FreeCoTaskMem(buffer);
       Console.WriteLine("\nInteger array passed ByRef after call:");
       foreach (int i in arrayRes)
       {
           Console.Write(" " + i);
       }

那么,将数组传递给这个要求long []并返回填充数组的C DLL函数的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我设法让它返回一些我可以变成数组并从中获取元素的东西。以下是它对我有用的方法:

IntPtr pointer = Marshal.AllocHGlobal(2048);
short b = GetImage.Invoke(imageUploadCounter, pointer);
int[] managedArray = new int[21];
Marshal.Copy(pointer, managedArray, 0, 21);
int imageID = managedArray[10];