DllImport,C/C++ -> C#,输出双精度数组

DllImport, C/C++ -> C#, out array of doubles

我想从 C++ 中获取双精度数组。
我用整数数组测试过,它工作正常,但我不知道双精度数组不能工作。
双精度数组的第一个和第二个元素是错误的。

还有一个奇怪的事情,我把FreeCoTaskMem注释掉了,因为如果我不这样做,应用程序会崩溃,ints和double是一样的。

任何提示给我,谢谢。

C/C++代码

#define DllExport __declspec(dllexport)
extern "C"
{       
   DllExport void TestOutOfInts(int** ints);
   DllExport void TestOutOfDoubles(double** doubles);
}

DllExport void TestOutOfInts(int** ints)
{
    int xyzs[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    (*ints) = xyzs;
}

DllExport void TestOutOfDoubles(double** doubles)
{   
    double xyzs[9] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };   
    (*doubles) = xyzs;
}

C#代码

[DllImport("MeshToolsWrapper.dll")]
static extern void TestOutOfInts(out IntPtr ints);

[DllImport("MeshToolsWrapper.dll")]
static extern void TestOutOfDoubles(out IntPtr doubles);

TestOutOfInts(out IntPtr ints);
int[] test1 = new int[9];
Marshal.Copy(ints, test1, 0, 9);
//Marshal.FreeCoTaskMem(ints);

TestOutOfDoubles(out IntPtr doubles); 
double[] test2 = new double[9];
Marshal.Copy(doubles, test2, 0, 9);
//Marshal.FreeCoTaskMem(doubles);

C# 结果

# ints
1
2
3
4
5
6
7
8
9

# doubles
1.16501519399776E-311
6.95245618745976E-310
3.3
4.4
5.5
6.6
7.7
8.8
9.9

这个:

DllExport void TestOutOfDoubles(double** doubles)
{   
    double xyzs[9] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };   
    (*doubles) = xyzs;
}

即使没有 C# 互操作也是未定义的行为。您正在返回一个指向堆栈内存的指针(数组)。下一个函数调用和 xyzs 的内容被破坏。几乎可以保证。

您的 TestOutOfInts 功能也是如此。你很幸运,它似乎有效。

这是修复:

DllExport void TestOutOfDoubles(double** doubles)
{   
    double xyzs[9] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };   
    double* result = new double[9];
    std::copy(xyzs, xysz+9, result);
    
    (*doubles) = result;
}

但是您需要提供另一个函数来释放已分配的内存,供 C# 代码调用。

更好的方法是强制调用者进行分配。有不同的技术,但我建议:

DllExport void TestOutOfDoubles(double* doubles, unsigned int size)
{   
    double xyzs[9] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };   

    if (size > 9)
    {
        size = 9;
    }

    std::copy(doubles, xyzs, xysz+size);

}

还有另一个提前检索尺寸的函数。

DllExport unsigned int GetDoubleArrayLength()
{   
   return 9; // or whatever the actual size is    
}

然后由 C# 代码进行数组分配。