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# 代码进行数组分配。
我想从 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# 代码进行数组分配。