【发布时间】:2011-07-01 15:15:42
【问题描述】:
我有一个带有导出函数的 C++ DLL:
extern "C" __declspec(dllexport) double* fft(double* dataReal, double* dataImag)
{
[...]
}
函数计算两个双精度数组(实部和虚部)的 FFT,并返回一个双精度数组,其中实部和虚部交错:{ Re, Im, Re, Im, ... }
我不确定如何在 C# 中调用此函数。 我正在做的是:
[DllImport("fft.dll")]
static extern double[] fft(double[] dataReal, double[] dataImag);
当我这样测试它时:
double[] foo = fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 });
我得到一个 MarshalDirectiveException 异常:
无法封送“返回值”:托管/非托管类型组合无效。
我假设这是因为 C++ double* 与 C# double[] 不太一样,但我不确定如何解决它。有什么想法吗?
编辑: 我已经更改了签名,以便现在传递一些额外的信息:
extern "C" __declspec(dllexport) void fft(double* dataReal, double* dataImag, int length, double* output);
我们总是知道output 的长度是length 的两倍
和
[DllImport("fft.dll")]
static extern void fft(double[] dataReal, double[] dataImag, int length, out double[] output);
这样测试:
double[] foo = new double[8];
fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 }, 4, out foo);
现在我得到的是 AccessViolationException 而不是 MarshalDirectiveException。
【问题讨论】:
-
它无法将 C++
double*转换为 C#double[],因为封送代码不知道数组的长度。根据您的描述,我假设它是输入数组的两倍,但我不知道 C++ 函数如何知道输入数组的长度。 -
C++ 函数像这样确定数组长度: int lengthReal = sizeof(dataReal) / sizeof(double); int lengthImag = sizeof(dataImag) / sizeof(double);
-
不,它没有。
dataReal只是一个指向double的指针,它的大小与数组中元素的数量无关,这就是数组在 C(++) 中作为参数传递的方式。另外:我们不知道谁的工作是释放结果数组(以及如何)。 -
好的,我明白了。 (对不起,我在 C# 与 C/C++ 方面的经验要多得多)。那么我还需要传递数组的长度吗?至于解除分配,它们不是在堆栈中吗?这意味着当函数结束时,内存会自动释放?如果不是,你如何建议我自己释放它?
标签: c# c++ interop marshalling dllimport