Question

I have an unmanaged C++ code and I want to convert it to managed C# code, the unmanaged code is shown below, I've searched but I did not find my answer...I want to know the right way for marshaling the below code, I am not sure how to marshal an enum and then reference it in an structure..the MMTPConxNack structure is a member of a union inside another structure. the hierarchy is shown below:

typedef enum
{
    MMTPCnxNckRsn_NoAnswer=-2,            
    MMTPCnxNckRsn_SendError=-1,         
    MMTPCnxNckRsn_Ok=0,                  
    MMTPCnxNckRsn_InvalidMember,         
    MMTPCnxNckRsn_HubNotReady,           
    MMTPCnxNckRsn_UnknownMember,         
    MMTPCnxNckRsn_LastCnxTooRecent,       
    MMTPCnxNckRsn_InvalidVersion,        
    MMTPCnxNckRsn_InvalidOptions,       
    MMTPCnxNckRsn_TooManyCnx             
} MMTPCnxNckRsn;

typedef struct
{
    MMTPCnxNckRsn Reason;
} MMTPConxNack;


typedef struct
{
    long Length;
    short Type;
    union
    {
        MMTPConxReq ConxReq;
        MMTPConxAck ConxAck;
        MMTPConxNack ConxNack; // the structure with an enum inside
        MMTPErrInd ErrInd;      
    } Data;  
} MMTPMsg;

actually I want to marshal the MMTPConxNack structure..and I use FieldOffset to define the size. Thanks in advance.

Was it helpful?

Solution

The enum looks like this:

public enum MMTPCnxNckRsn {
    MMTPCnxNckRsn_NoAnswer = -2, 
    MMTPCnxNckRsn_SendError = -1, 
    MMTPCnxNckRsn_Ok = 0, 
    MMTPCnxNckRsn_InvalidMember,         
    MMTPCnxNckRsn_HubNotReady,           
    MMTPCnxNckRsn_UnknownMember,         
    MMTPCnxNckRsn_LastCnxTooRecent,       
    MMTPCnxNckRsn_InvalidVersion,        
    MMTPCnxNckRsn_InvalidOptions,       
    MMTPCnxNckRsn_TooManyCnx             
}

The containing struct is:

public struct MMTPConxNack {
    public MMTPCnxNckRsn Reason; 
}

The union is:

[StructLayout(LayoutKind.Explicit)]
public struct MMTPMsgDataUnion
{
    [FieldOffset(0)]
    public MMTPConxReq ConxReq;
    [FieldOffset(0)]
    public MMTPConxAck ConxAck;
    [FieldOffset(0)]
    public MMTPConxNack ConxNack;
    [FieldOffset(0)]
    public MMTPErrInd ErrInd;
}

This is the tricky part. You use LayoutKind.Explicit and FieldOffset to specify that all the members of the C++ union is overlayed on each other. Obviously you need to have definitions for the other 3 types contained in this union, definitions that we cannot see in the C++ code in the question. I presume you already know how to define those.

Once you have the union declared, the final structure is simple:

public struct MMTPMMsg
{
    public int Length;
    public short Type;
    public MMTPMsgDataUnion Data;
}

OTHER TIPS

You need a C# enum and struct to match the native ones:

public enum MMTPCnxNckRsn
{
    MMTPCnxNckRsn_NoAnswer,            
    MMTPCnxNckRsn_SendError,         
    MMTPCnxNckRsn_Ok,                  
    MMTPCnxNckRsn_InvalidMember,         
    MMTPCnxNckRsn_HubNotReady,           
    MMTPCnxNckRsn_UnknownMember,         
    MMTPCnxNckRsn_LastCnxTooRecent,       
    MMTPCnxNckRsn_InvalidVersion,        
    MMTPCnxNckRsn_InvalidOptions,       
    MMTPCnxNckRsn_TooManyCnx             
}

public struct MMTPConxNack
{
    public readonly MMTPCnxNckRsn Reason;
}

And you marshal it like this:

var managedItem = (MMTPConxNack)Marshal.PtrToStructure(pointer,typeof(MMTPConxNack));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top