2

i have a problem with convert a struct c++ to c# struct, i will leave the following code:

C++

struct SDK_ALARM_INPUTCONFIG
{
bool    bEnable;        
int     iSensorType;    
SDK_EventHandler hEvent;    
};

struct SDK_EventHandler
{
unsigned int    dwRecord;               
int     iRecordLatch;               
unsigned int    dwTour;                     
unsigned int    dwSnapShot;             
unsigned int    dwAlarmOut;             
unsigned int    dwMatrix;               
int     iEventLatch;            
int     iAOLatch;                 
SDK_PtzLinkConfig PtzLink[NET_MAX_CHANNUM];     
SDK_CONFIG_WORKSHEET schedule;      

bool    bRecordEn;              
bool    bTourEn;                 
bool    bSnapEn;                    
bool    bAlarmOutEn;            
bool    bPtzEn;


bool    bTip;                       
bool    bMail;                      
bool    bMessage;                   
bool    bBeep;                      
bool    bVoice;                         
bool    bFTP;                   
bool    bMatrixEn;              
bool    bLog;                   
bool    bMessagetoNet;           

bool    bShowInfo;              
unsigned int    dwShowInfoMask;         
char    pAlarmInfo[8];

bool    bShortMsg;              
bool    bMultimediaMsg;         
};

struct SDK_PtzLinkConfig
{
int iType;      
int iValue;      
};


struct SDK_CONFIG_WORKSHEET
{   
SDK_TIMESECTION tsSchedule[6][7];
};

 struct SDK_TIMESECTION
    {

        int enable;
        int startHour;
        int startMinute;
        int startSecond;
        int endHour;
        int endMinute;
        int endSecond;
    };

C#:

[StructLayout(LayoutKind.Sequential)]
public struct SDK_ALARM_INPUTCONFIG
{
    public bool bEnable;
    public int iSensorType;
    public SDK_EventHandler hEvent;
};

   [StructLayout(LayoutKind.Sequential)]
   public struct SDK_EventHandler
{
   public ushort dwRecord;
   public int iRecordLatch;
   public ushort dwTour;
   public ushort dwSnapShot;
   public ushort dwAlarmOut;
   public ushort dwMatrix;
   public int iEventLatch;
   public int iAOLatch;

   [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.Struct, SizeConst = 32)]
   public SDK_PtzLinkConfig[] PtzLink;

   public SDK_CONFIG_WORKSHEET schedule;

   public bool bRecordEn;
   public bool bTourEn;
   public bool bSnapEn;
   public bool bAlarmOutEn;
   public bool bPtzEn;
   public bool bTip;
   public bool bMail;
   public bool bMessage;
   public bool bBeep;
   public bool bVoice;
   public bool bFTP;
   public bool bMatrixEn;
   public bool bLog;
   public bool bMessagetoNet;

   public bool bShowInfo;
   public ushort dwShowInfoMask;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
   public string pAlarmInfo;

   //public bool bShortMsg;
   //public bool bMultimediaMsg;         
};
[StructLayout(LayoutKind.Sequential)]
public struct SDK_PtzLinkConfig
{
    public int iType;
    public int iValue;  
};
[StructLayout(LayoutKind.Sequential)]
public struct SDK_CONFIG_WORKSHEET
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.Struct, SizeConst = 6*7)]
    public SDK_TIMESECTION[] tsSchedule;
};

[StructLayout(LayoutKind.Sequential)]
 struct SDK_TIMESECTION
    {

        public int enable;
        public int startHour;
        public int startMinute;
        public int startSecond;
        public int endHour;
        public int endMinute;
        public int endSecond;
    };

I'm calling this method:

C++:

long  H264_DVR_GetDevConfig(long lLoginID, unsigned long dwCommand, int nChannelNO, char * lpOutBuffer, unsigned long dwOutBufferSize, unsigned long* lpBytesReturned,int waittime = 1000);

C#:

 [DllImport("NetSdk.dll")]
        public static extern int H264_DVR_GetDevConfig(int lLoginID, uint dwCommand, int nChannelNO, IntPtr lpOutBuffer, 
            uint dwOutBufferSize, ref uint lpBytesReturned, int waittime);

I'm calling this way:

C#:

var vAlarmConfig = new SDK_ALARM_INPUTCONFIG();

        IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SDK_ALARM_INPUTCONFIG)));

        Marshal.StructureToPtr(vAlarmConfig, ptr, true);
        uint lpBytesReturned = (uint)Marshal.SizeOf(typeof(SDK_ALARM_INPUTCONFIG));
        int CHANNEL = 2;

        int result = XMSDK.H264_DVR_GetDevConfig(lLoginID, (uint)SDK_CONFIG_TYPE.E_SDK_CONFIG_ALARM_IN, CHANNEL, ptr,
            (uint)Marshal.SizeOf(typeof(SDK_ALARM_INPUTCONFIG)), ref lpBytesReturned, 10000);

Seems everything work fine, but when i run the program, the method return an illegal paramater.

What i'm doing wrong?. I think the problem is the conversion.

Regards.

4
  • int can mean different things depending on your C platform/compiler/settings. You need to start by figuring out what it means here. Commented Jan 10, 2014 at 1:29
  • I'm based my code from an example and they have int(c++) as int (c#), i proved some methods in my c# code and everything works except this. Commented Jan 10, 2014 at 1:42
  • @JonathanWood No. On Windows, int is the same in C# and C++. Commented Jan 10, 2014 at 1:43
  • It would be easier to declare the p/invokes using the C# struct types rather than IntPtr. Then you can let the marshaler do the work and you can avoid all those Marshal method calls. Commented Jan 10, 2014 at 1:50

1 Answer 1

4

Your C++ bool is a single byte. But the C# bool default marshaling is as the 4 byte Winapi BOOL type. You'll need to add [MarshalAs(UnmanagedType.U1)] for every bool in your structs.

Your use of ushort is wrong. On the C++ side you have unsigned int. That is uint on the C# side.

You will also need to translate the structs accurately. Perhaps while you were debugging you made pAlarmInfo have length 64 rather than 8. Obviously you need to go back an do that correctly.

I guess you made that change because the struct size was incorrect. That should have been a tell-tale sign that there was a more serious problem. Your structs have to line up for each and every member. You can't just add a load of padding at the end to get the size right. If the sizes don't match then the layout will be wrong. You make the sizes match as a consequence of making the layouts match. When the latter is done correctly, the former happens as a consequence.

Sign up to request clarification or add additional context in comments.

2 Comments

ok, i will do it the changes, by the way pAlarmInfo is 64 not 8, my mistake.
thanks for helping me, you are right, i changed ushort for uint and i made a little changes and the code it's working!!! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.