Help with passing structure from unmanaged c++ dll to c# ?
I am struggling with passing a structure from an unmanaged third party c++ dll back into my c# application. The dll is for a spectrometer. All of the other commands to the spectrometer work fine except this one. I am pasting more documentation below, but here is the c++ call:
SDK_API MTSSE_GetDeviceSpectrometerFrameData( int DeviceID, int SpectrometerID, int WaitUntilDone, tFrameRecord* &FrameData);
and it is the last argument that is the problem. The documentation says this:
FrameRecordData - the pointer to the spectrum data structure if spectrum is ready or nil if spectrum is not ready. It is defined as:
typedef struct
{
double* CCDData;
double* CalibData;
double* AbsIntenData
}tFrameRecord;
And each item again should points to a double data array which defined as double data[3648].
First I tried this (in the namespace):
public struct MTFrameRecordData
{
public double[] CCDData;
public double[] CalibData;
public double[] AbsIntenData;
}
With this in a class called myUSBCam, that holds the wrappers:
public int MTGetDeviceSpectrometerFrameData(int DeviceID, int SpectrometerID, int WaitUntilDone, MTFrameRecordData FrameData)
{
int numOut = MT_GetDeviceSpectrometerFrameData(DeviceID, SpectrometerID, WaitUntilDone, FrameData);
if (numOut < 0)
{
MessageBox.Show("Error trying to SetDeviceExposureTime. No cameras found on USB 2.0 bus.", _camError, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return numOut;
}
[DllImport("MT_Spectrometer_SDK.dll", EntryPoint = "MTSSE_GetDeviceSpectrometerFrameData", CallingConvention = CallingConvention.StdCall)]
private static extern int MT_GetDeviceSpectrometerFrameData(int DeviceID, int SpectrometerID, int WaitUntilDone, MTFrameRecordData FrameData);
And then I call this in my main application (nInit is equal to 1):
int numOut5 = 0;
while (numOut5 <= 0)
{
System.Threading.Thread.Sleep(20);
numOut5 = myUSBCam.MTGetDeviceSpectrometerFrameData(nInit, 1, 1, frameRecordData);
}
With this I get the error message:
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in USBCam.exe
Additional information: Cannot marshal 'parameter #4': Invalid managed/unmanaged type combination.
I also tried this for the declaration of the structure (again in the name space):
[StructLayout(LayoutKind.Explicit)]
public struct MTFrameRecordData
{
[FieldOffset(0)]
public double[] CCDData;
[FieldOffset(29184)]
public double[] CalibData;
[FieldOffset(58368)]
public double[] AbsIntenData;
}
This produces the error messsage
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in USBCam.exe
Additional information: Internal limitation: method signature is too complex or too large.
Can anyone help me with how to pass the structure from the unmanaged c++ dll into my c# application?
Begin more detailed description from the documentation:
SDK_API MTSSE_GetDeviceSpectrometerFrameData( int DeviceID, int SpectrometerID, int WaitUntilDone, tFrameRecord* &FrameData);
After sending the above MTSSE_StartGrabSpectrum() command, user can invoke this function to check whether the spectrum is ready and to get the spectrum.
Arguments: DeviceID -- the index of the device, Please refer to the notes of MTSSE_InitDevice() function.
SpectrometerID – the index of the spectrometer, should always be set to 1.
FrameRecordData - the pointer to the spectrum data structure if spectrum is ready or nil if spectrum is not ready. It is defined as:
typedef struct
{
double* CCDData;
double* CalibData;
double* AbsIntenData
}tFrameRecord;
And each item again should points to a double data array which defined as double data[3648].
CCDData is the raw pixel data,
CalibData is the CCDDataa with ETC calibration (if etc flag was turned on), if ETC is off, it should equal the CCDData.
AbsIntenData returns the absolute intensity data if AIC coefficients exists
WaitUntilDone – the frame grabbing process may need considerable time (depends on the exposure time setting and average frame number setting). User might set:
1: The API will be blocked until the spectrum is grabbed, the returned spectrum is pointed by the FrameRecordData, If the returned pointer is nil, “Time out” error occurs.
0: The API will not be blocked, if the spectrum is ready, the spectrum will be returned in FrameRecordData), otherwise, it will return nil.
Return: -1, if the grabbing command is not finished (when WaitUntilDone is “0”) or “Time out” error occurs (when WaitUntilDone is “1”).
1, if function succeeds.