将托管代码中的多维数组传递给非托管代码

时间:2011-08-22 20:57:38

标签: c# c++ marshalling dllimport

我想做以下事情:

  1. 在c#代码中创建三个像素数组,如下所示:

    var myArray = new short[x,y,z];
    UnanagedFunction(myArray);
    
  2. 将其传递给非托管代码(c ++),如下所示:

    void UnmanagedFunction(short*** myArray)
    {
        short first = myArray[0][0][0];
    }
    
  3. 已更新 当我尝试以下代码时,我遇到了运行时错误:

      

    尝试读取或写入受保护的内存。

    谢谢!!!

2 个答案:

答案 0 :(得分:7)

IntPtr Array3DToIntPtr(short[, ,] Val)
        {
            IntPtr ret = Marshal.AllocHGlobal((Val.GetLength(0) + Val.GetLength(1) + Val.GetLength(2)) * sizeof(short));

            int offset = 0;
            for (int i = 0; i < Val.GetLength(0); i++)
            {

                for (int j = 0; j < Val.GetLength(1); j++)
                {
                    for (int k = 0; k < Val.GetLength(2); k++)
                    {
                        Marshal.WriteInt16(ret,offset, Val[i, j, k]);
                        offset += sizeof(short);


                    }
                }
            }

            return ret;
        }

这已经过测试并且可以正常工作,唯一的限制是当你完成它时你必须在数组指针上调用Marshal.FreeHGlobal或者你会得到内存泄漏,我还建议你改变您的c ++函数,以便它接受数组维度,或者您只能使用特定大小的3d数组

答案 1 :(得分:2)

我是用纯C#编写的,但是如果从unsafe static中删除FuncFunc应该在C / C ++中工作。请注意,我注意到确定可以写这个:-) 我正在使用此Indexing into arrays of arbitrary rank in C#

static unsafe void Main(string[] args) {
    var myArray = new short[5, 10, 20];

    short z = 0;

    for (int i = 0; i < myArray.GetLength(0); i++) {
        for (int j = 0; j < myArray.GetLength(1); j++) {
            for (int k = 0; k < myArray.GetLength(2); k++) {
                myArray[i, j, k] = z;
                z++;
            }
        }
    }

    // myArray[1, 2, 3] == 243

    fixed (short* ptr = myArray) {
        Func(ptr, myArray.GetLength(0), myArray.GetLength(1), myArray.GetLength(2));
    }
}

// To convert to C/C++ take away the static unsafe
static unsafe void Func(short* myArray, int size1, int size2, int size3) {
    int x = 1, y = 2, z = 3;
    int el = myArray[x * size2 * size3 + y * size3 + z]; // el == 243
}