2

I have the following c++ struct

typedef struct {
    char    szAccountNo[11];        
    char    szAccountName[40];      
    char    act_pdt_cdz3[3];        
    char    amn_tab_cdz4[4];        
    char    expr_datez8[8];         
    char    granted;                
    char    filler[189];            
}ACCOUNTINFO;

typedef struct {
    char    szDate          [14];   
    char    szServerName    [15];   
    char    szUserID        [8];    
    char    szAccountCount  [3];    
    ACCOUNTINFO accountlist [999];  
}LOGININFO;

typedef struct{
    int       TrIndex;
    LOGININFO *pLoginInfo;
}LOGINBLOCK;

and converted into C# class

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public class ACCOUNTINFO
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
            public string szAccountNo;      
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
            public string szAccountName;        
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string act_pdt_cdz3;     
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string amn_tab_cdz4;     
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string expr_datez8;          
            public char granted;                
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 189)]
            public string filler;           
        };
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public class LOGININFO
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
            public string szDate;   
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
            public string szServerName; 
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string szUserID; 
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string szAccountCount;   
            [MarshalAs(UnmanagedType.Struct, SizeConst = 99)]
            public ACCOUNTINFO[] accountlist;   
        };
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public class LOGINBLOCK
        {
            [MarshalAs(UnmanagedType.I4)]
            public int TrIndex;
            [MarshalAs(UnmanagedType.Struct, SizeConst = 1)]
            public LOGININFO pLoginInfo;
        };

I used the following two methods to convert the LParam within the WndProc.

1. TrStruct.LOGINBLOCK lb = new TrStruct.LOGINBLOCK();
                        lb = (TrStruct.LOGINBLOCK)m.GetLParam(typeof(TrStruct.LOGINBLOCK));

2. TrStruct.LOGINBLOCK lb = (TrStruct.LOGINBLOCK) Marshal.PtrToStructure(m.LParam, typeof(TrStruct.LOGINBLOCK));

However, it doesn't get success nor emits an regular error message, instead I get the message "A first chance exception of type 'System.TypeLoadException' occurred in mscorlib.dll" in Output window. Could anyone tell me what's wrong with my conversion?

icewall
  • 111
  • 6
  • 1
    For starters, your charset is ascii, not unicode. Also use the `fixed` keyword for value arrays. – leppie Feb 18 '13 at 07:21
  • @leppie I don't understand using fixed keyword for value arrays. Could you be more specific or give an example? – icewall Feb 18 '13 at 08:52
  • See http://msdn.microsoft.com/en-us/library/zycewsya(v=vs.80).aspx – leppie Feb 18 '13 at 08:57
  • @leppie I still don't get where I should use 'fixed'. It seems that you refering to ACCOUNTINFO[] array, but the array should refer to the ACCOUNTINFO type. And I counldn't use 'fixed' for the non-primitive type ACCOUNTINFO – icewall Feb 18 '13 at 12:47
  • Sorry, I did not realize they wont work on classes with layout. Use a struct then. – leppie Feb 18 '13 at 13:17
  • @leppie It won't work with struct either. "Fixed size buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double" – icewall Feb 18 '13 at 23:46

1 Answers1

0

The first apparent problem with your code lies in CharSet.Unicode. Fields of you structure in unmanaged code are all defined as char which is a single-byte character. You should use CharSet.Ansi for all your structures.

The second problem is in last field of LOGININFO. It is defined as

[MarshalAs(UnmanagedType.Struct, SizeConst = 99)]
public ACCOUNTINFO[] accountlist;

but in your unmanaged code, it is

ACCOUNTINFO accountlist [999];

The SizeConst parameter should be changed to 999.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72