将多维数组从托管代码传递到非托管代码

Posted

技术标签:

【中文标题】将多维数组从托管代码传递到非托管代码【英文标题】:Pass multi - dimensional array from managed code to unmanaged code 【发布时间】:2011-11-01 11:36:05 【问题描述】:

我想做以下事情:

    在 C# 代码中创建三个维度数组,如下所示:

    var myArray = new short[x,y,z];
    UnanagedFunction(myArray);
    

    像这样将它传递给非托管代码 (c++):

    void UnmanagedFunction(short*** myArray)
    
        short first = myArray[0][0][0];
    
    

更新 当我尝试以下代码时,出现运行时错误:

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

谢谢!!!

【问题讨论】:

你不能用 C++ 编写这样的代码。 代码的第一部分在 c# 中,第二部分在 c++ 中,我现在尝试了编译器允许我使用 c++ 代码 也许您可以将代码更改为三元组数组。 @Simon,一组三元组有什么帮助?您是指四倍(x、y、z 和值)吗? 你甚至不能在纯 C++ 中做到这一点。您必须在函数原型上编写除一维之外的所有维度。阅读:c-faq.com/~scs/cclass/int/sx9a.html(例如void UnmanagedFunction(short myArray[][10][10])) 【参考方案1】:
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 数组

【讨论】:

【参考方案2】:

我是用纯 C# 编写的,但如果你从 Func 中去掉 unsafe staticFunc 应该可以在 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

【讨论】:

以上是关于将多维数组从托管代码传递到非托管代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 ATL/COM 将托管字节 [] 转换为非托管字节数组

如何使用 C++/CLI Wrapper 将变量参数从托管传递到非托管?

将回调参数从 C# 传递到非托管 C++

如何在托管 (C#) 和非托管 (C++) 代码之间来回传递数组内容

从 c# dll 调用/编组字符串到非托管代码

在托管代码和非托管代码之间传递非托管结构的安全数组