我需要将c#中的双精度数组转换为IntPtr,才能将其正确发送到我的c DLL。我已经能够使用此答案中的方法成功地将IntPtr转换为double [,] 。Ive还找到了另一个答案,该答案与我需要的答案很接近,但涉及一维数组。
我在逻辑上缺少某些内容,崩溃后得到错误代码:Managed'已退出,代码为-1073740940(0xc0000374)。
这就是我到目前为止
IntPtr p = Marshal.AllocHGlobal(rows * columns);
for (int i = 0; i < rows; i++) //rows
{
double[] temp = new double[columns];
for (int x = 0; x < columns; x++)
temp[x] = input.cells[i, x];
Marshal.Copy(temp, 0, p, columns);
p = (IntPtr)(p.ToInt64() + IntPtr.Size);
}
toReturn.cells = p;
Marshal.FreeHGlobal(p);
return toReturn;
toReturn.cells是我返回的结构内的IntPtr。单元格的结构为单元格[行,列]
IntPtr对我来说还是很新的。
编辑:感谢哈罗德。他们的建议效果很好
这有很多问题。
首先,rows * columns
不是数据的大小,而是元素的总数。这些元素不是每个字节一个,而是八个,或者sizeof(double)
您愿意的话。
其次,通过p
进行更新p = (IntPtr)(p.ToInt64() + IntPtr.Size);
(即,根据当前模式下的指针大小将其前进4或8个字节),但是您已写入columns * 8
(或columns * sizeof(double)
)字节的数据。前进p
不到columns * 8
会使写入彼此覆盖,因此并非所有数据最终都会出现在结果中。顺便说一下,这里实际上不需要复杂的转换IntPtr
,因为.NET 4可以直接添加到。
第三,p
在循环中进行更改,这本身并不坏,但是这样做的方式会丢失对原始指针的跟踪。toReturn.cells = p;
并Marshal.FreeHGlobal(p);
使用p
不指向您分配的区域的,他们使用p
,现在指向数据的末尾(如果p
以正确的数量更新,它将指向该区域)。p
必须记住原件。
第四,在返回数据之前释放数据意味着它现在已经不存在了,所以无论该数据传递给什么代码,它都仍然没有:它有一个指向无用的指针,该指针将无效使用(它可能会偶然地起作用,但是这是危险的和错误的)。
前三点很容易解决,但后三点需要对应用程序的工作方式进行非本地更改:无法在此处释放内存,但是应该在某个时候释放内存,即在数据用户完成操作时释放用它。
应用了一些修复程序:
int stride = columns * sizeof(double);
IntPtr p = Marshal.AllocHGlobal(rows * stride);
for (int i = 0; i < rows; i++) //rows
{
double[] temp = new double[columns];
for (int x = 0; x < columns; x++)
temp[x] = input.cells[i, x];
Marshal.Copy(temp, 0, p + stride * i, columns);
}
toReturn.cells = p;
return toReturn;
请记住,您仍然应该在适当的时间释放内存。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句