I am trying to Marshall the following structure
struct OpalMessage {
OpalMessageType m_type; ///< Type of message
union {
const char * m_commandError; ///< Used by OpalIndCommandError
OpalParamGeneral m_general; ///< Used by OpalCmdSetGeneralParameters
OpalParamProtocol m_protocol; ///< Used by OpalCmdSetProtocolParameters
OpalParamRegistration m_registrationInfo; ///< Used by OpalCmdRegistration
OpalStatusRegistration m_registrationStatus; ///< Used by OpalIndRegistration
OpalParamSetUpCall m_callSetUp; ///< Used by OpalCmdSetUpCall/OpalIndProceeding/OpalIndAlerting/OpalIndEstablished
const char * m_callToken; ///< Used by OpalCmdHoldcall/OpalCmdRetrieveCall/OpalCmdStopRecording
OpalStatusIncomingCall m_incomingCall; ///< Used by OpalIndIncomingCall
OpalParamAnswerCall m_answerCall; ///< Used by OpalCmdAnswerCall/OpalCmdAlerting
OpalStatusUserInput m_userInput; ///< Used by OpalIndUserInput/OpalCmdUserInput
OpalStatusMessageWaiting m_messageWaiting; ///< Used by OpalIndMessageWaiting
OpalStatusLineAppearance m_lineAppearance; ///< Used by OpalIndLineAppearance
OpalStatusCallCleared m_callCleared; ///< Used by OpalIndCallCleared
OpalParamCallCleared m_clearCall; ///< Used by OpalCmdClearCall
OpalStatusMediaStream m_mediaStream; ///< Used by OpalIndMediaStream/OpalCmdMediaStream
OpalParamSetUserData m_setUserData; ///< Used by OpalCmdSetUserData
OpalParamRecording m_recording; ///< Used by OpalCmdStartRecording
OpalStatusTransferCall m_transferStatus; ///< Used by OpalIndTransferCall
OpalStatusIVR m_ivrStatus; ///< Used by OpalIndCompletedIVR
} m_param;
};
over to C#. The obvious problem is the two strings which will inevitably be reference types.
So, I tried this:
[StructLayout(LayoutKind.Explicit)]
public struct OpalMessageStrUnion
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.LPStr)]
public string m_commandError; ///< Used by OpalIndCommandError
[FieldOffset(0)]
[MarshalAs(UnmanagedType.LPStr)]
public string m_callToken; ///< Used by OpalCmdHoldcall/OpalCmdRetrieveCall/OpalCmdStopRecording
}
[StructLayout(LayoutKind.Explicit)]
public struct OpalMessageUnion
{
[FieldOffset(0)]
public OpalParamGeneral m_general; ///< Used by OpalCmdSetGeneralParameters
[FieldOffset(0)]
public OpalParamProtocol m_protocol; ///< Used by OpalCmdSetProtocolParameters
[FieldOffset(0)]
public OpalParamRegistration m_registrationInfo; ///< Used by OpalCmdRegistration
[FieldOffset(0)]
public OpalStatusRegistration m_registrationStatus; ///< Used by OpalIndRegistration
[FieldOffset(0)]
public OpalParamSetUpCall m_callSetUp; ///< Used by OpalCmdSetUpCall/OpalIndProceeding/OpalIndAlerting/OpalIndEstablished
[FieldOffset(0)]
public OpalStatusIncomingCall m_incomingCall; ///< Used by OpalIndIncomingCall
[FieldOffset(0)]
public OpalParamAnswerCall m_answerCall; ///< Used by OpalCmdAnswerCall/OpalCmdAlerting
[FieldOffset(0)]
public OpalStatusUserInput m_userInput; ///< Used by OpalIndUserInput/OpalCmdUserInput
[FieldOffset(0)]
public OpalStatusMessageWaiting m_messageWaiting; ///< Used by OpalIndMessageWaiting
[FieldOffset(0)]
public OpalStatusLineAppearance m_lineAppearance; ///< Used by OpalIndLineAppearance
[FieldOffset(0)]
public OpalStatusCallCleared m_callCleared; ///< Used by OpalIndCallCleared
[FieldOffset(0)]
public OpalParamCallCleared m_clearCall; ///< Used by OpalCmdClearCall
[FieldOffset(0)]
public OpalStatusMediaStream m_mediaStream; ///< Used by OpalIndMediaStream/OpalCmdMediaStream
[FieldOffset(0)]
public OpalParamSetUserData m_setUserData; ///< Used by OpalCmdSetUserData
[FieldOffset(0)]
public OpalParamRecording m_recording; ///< Used by OpalCmdStartRecording
[FieldOffset(0)]
public OpalStatusTransferCall m_transferStatus; ///< Used by OpalIndTransferCall
[FieldOffset(0)]
public OpalStatusIVR m_ivrStatus; ///< Used by OpalIndCompletedIVR
}
/// <summary>
/// Message to/from OPAL system.
/// This is passed via the OpalGetMessage() or OpalSendMessage() functions.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct OpalMessage
{
//this guy is an enumeration b.t.w.
/// <summary>
/// type of message
/// </summary>
[FieldOffset(0)]
public OpalMessageType m_type;
[FieldOffset(4)]
public OpalMessageUnion m_param;
[FieldOffset(4)]
public OpalMessageStrUnion m_strParam;
}
However, I am still getting the marshaling error telling me that this won't work because I am mixing an object with non-object types in the same memory location. I am now assuming that the structures themselves (i.e. OpalParamGeneral and the like) also cannot mix reference and value types even though they are laid out sequentially?
Doing a separate function call for each structure is not an option by the way. I would rather write a COM wrapper than do that.