将多维数组从托管代码传递到非托管代码
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 static
,Func
应该可以在 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 将变量参数从托管传递到非托管?