I have a C++ DLL with an exported function:
extern "C" __declspec(dllexport) double* fft(double* dataReal, double* dataImag)
{
[...]
}
The function calculates the FFT of the two double arrays (real and imaginary) an returns a single double array with the real an imaginary components interleaved: { Re, Im, Re, Im, ... }
I'm not sure how to call this function in C#. What I'm doing is:
[DllImport("fft.dll")]
static extern double[] fft(double[] dataReal, double[] dataImag);
and when I test it like this:
double[] foo = fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 });
I get a MarshalDirectiveException exception:
Cannot marshal 'return value': Invalid managed/unmanaged type combination.
I'm assuming this is because C++ double*
isn't quite the same as C# double[]
, but I'm not sure how to fix it. Any ideas?
Edit: I've changed the signatures so that I now pass some extra information:
extern "C" __declspec(dllexport) void fft(double* dataReal, double* dataImag, int length, double* output);
We always know the length of output
will be 2x length
and
[DllImport("fft.dll")]
static extern void fft(double[] dataReal, double[] dataImag, int length, out double[] output);
tested like this:
double[] foo = new double[8];
fft(new double[] { 1, 2, 3, 4 }, new double[] { 0, 0, 0, 0 }, 4, out foo);
Now I'm getting an AccessViolationException rather than a MarshalDirectiveException.
There are a few problems with your example:
Instead, my suggestion would be to define fft this way:
extern "C" __declspec(dllexport) void __stdcall fft(double const* dataReal, int dataRealLength, double const* dataImag, int dataImagLength, double* result, int resultLength)
{
// Check that dataRealLength == dataImagLength
// Check that resultLength is twice dataRealLength
}
The corresponding P/Invoke signature would be:
[DllImport("fft.dll")]
static extern void fft(double[] dataReal, int dataRealLength, double[] dataImag, int dataImagLength, double[] result, int resultLength);
And then an example of a call:
double[] dataReal = new double[] { 1.0, 2.0, 3.0, 4.0 };
double[] dataImag = new double[] { 5.0, 6.0, 7.0, 8.0 };
double[] result = new double[8];
fft(dataReal, dataReal.Length, dataImag, dataImag.Length, result, result.Length);
Edit: updating based on what fft is described to do.