DllImport,C/C++->C#,输出双精度数组
c#
我想从 C++ 获取双打数组。
我用整数数组进行了测试,它工作正常,但我不知道双精度数组不能工作。
双精度数组的第一个和第二个元素是错误的。
还有一个奇怪的事情,我把FreeCoTaskMem注释掉了,因为如果我不注释,应用程序就会崩溃,ints和doubles是一样的。
给我任何提示,谢谢。
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# 代码来进行数组分配。