IntPtr 到三维数组

IntPtr to three dimensional array

我正在我的 C# 项目中使用 C++ dll。使用 pInvoke(平台调用)。

我的 C++ 代码 returns 一个 double***,C# 函数 returns 一个 IntPtr。

我有矩阵两边的维度,只是它们不是常量。

在 C# 方面我有:

[DllImport("mylib.dll")]
public static extern IntPtr GetMatrix(int width, int height, int depth);

在 C++ 方面我有:

extern "C" {
    __declspec(dllexport) double*** GetMatrix(int width, int height, int depth) {
        // do stuff
        return matrix;
    }
}

现在我需要将这个 IntPtr 转换为 double[],但是,我不知道该怎么做。

基本上我需要this question答案的反义词。

我从来没有用这些类型的数组尝试过,但是第一个解决方案可能有效,我被 this MSDN article:

引导相信

(请注意,这仅在您可以在 C# 端更改函数定义时才有效)在您的 C# 函数中,将 IntPtr 参数更改为 double[,,] 参数并将此 MarshalAs 属性添加到它, 类似于上面 MSDN 文章的做法。

[DllImport("FooBar.dll")]
extern void Foo([MarshalAs(UnmanagedType.LPArray, SizeConst=**YOUR ARRAY SIZE HERE**)] double[,,] bar);

这还假设您有一个固定大小的数组,我不确定这将如何与 3d 数组一起工作,但是如果您想进一步研究这种类型的解决方案,这里是完整的MarshalAsAttribute.

的文档

另一个解决方案与另一个问题的相反答案非常相似。您可以将 double[,,] 初始化为您需要的任何大小,然后开始使用 Marshal.Copy (this overload) 填充行。您还可以编组具有相同功能的单个双精度数。像这样:

double[,,] arr = new double[25, 25, 200];
int il = arr.GetLength(0), jl = arr.GetLength(1), kl = arr.GetLength(2);

IntPtr values = DllFoo();

for (int i = 0; i < il; i++)
{
    for (int j = 0; j < jl; j++)
    {
        for (int k = 0; k < kl; k++)
        {
            double[] temp = new double[1];
            arr[i,j,k] = Marshal.Copy(values, temp, 1, k + j * jl + k * jl * kl);
        }
    }    
}

您绝对可以从该代码段中获得更多性能,但它应该仍然有效。