CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Apr 2004
    Posts
    102

    How to resolve a PInvokeStackImbalance was detected issue

    I have started converting a C SDK to C# and have encountered a PInvokeStackImbalance was detected error that I just can't figure out how to resolve.

    The details of the message is as follows:

    PInvokeStackImbalance was detected
    Message: A call to PInvoke function 'PInvoke!PlatformInvokeTest::CLIENT_Logout' has unbalanced the stack.
    This is likely because the managed PInvoke signature does not match the unmanaged target signature.
    Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
    Some info from the C SDK header file follows:

    Code:
    #ifndef LLONG
    #ifdef WIN32
    #define LLONG LONG
    #else //WIN64 
    #define LLONG INT64
    #endif
    #endif
    
    #ifndef CLIENT_API
    #define CLIENT_API  __declspec(dllexport) 
    #endif
    
    #else
    
    #ifndef CLIENT_API
    #define CLIENT_API  __declspec(dllimport)
    #endif
    
    #endif
    
    #define CALLBACK __stdcall
    #define CALL_METHOD  __stdcall  //__cdecl
    
    
    // Register to the device 
    CLIENT_API LLONG CALL_METHOD CLIENT_Login(char *pchDVRIP, WORD wDVRPort, char *pchUserName, char *pchPassword, LPNET_DEVICEINFO lpDeviceInfo, int *error = 0);
    
    // Log out the device 
    CLIENT_API BOOL CALL_METHOD CLIENT_Logout(LLONG lLoginID);
    and finally my source code...

    Code:
    using System;
    using System.Runtime.InteropServices;
    
    class PlatformInvokeTest
    {
        static public long lLogin;
    
        public delegate void fDisConnect(long lLoginID, IntPtr pchDVRIP, long nDVRPort, uint dwUser);
        public delegate void fHaveReConnect(long lLoginID, IntPtr pchDVRIP, long nDVRPort, uint dwUser);
    
        //  [DllImport("dhnetsdk.dll", CallingConvention = CallingConvention.StdCall)]
        [DllImport("dhnetsdk.dll")]
        public static extern bool CLIENT_Init(fDisConnect cbDisConnect, uint dwUser);
    
      //  [DllImport("dhnetsdk.dll", CallingConvention = CallingConvention.StdCall)]
          [DllImport("dhnetsdk.dll")]
        public static extern void CLIENT_SetAutoReconnect(fHaveReConnect cbHaveReconnt, uint dwUser);
    
     //   [DllImport("dhnetsdk.dll", CallingConvention = CallingConvention.StdCall)]
          [DllImport("dhnetsdk.dll")]
        public static extern long CLIENT_Login(string pchDVRIP, ushort wDVRPort, string pchUserName, string pchPassword, NET_DEVICEINFO lpDeviceInfo, IntPtr error);
    
       // [DllImport("dhnetsdk.dll", CallingConvention = CallingConvention.StdCall)]
          [DllImport("dhnetsdk.dll")]
        public static extern bool CLIENT_Logout(long lID);
    
        // [DllImport("dhnetsdk.dll", CallingConvention = CallingConvention.StdCall)]
          [DllImport("dhnetsdk.dll")]
        public static extern void CLIENT_Cleanup();
    
        static int[] long2doubleInt(long a)
        {
            int a1 = (int)(a & uint.MaxValue);
            int a2 = (int)(a >> 32);
            return new int[] { a1, a2 };
        }
    
        public static void fDisConnectMethod(long lLoginID, IntPtr pchDVRIP, long nDVRPort, uint dwUser)
        {
            System.Console.WriteLine("Disconnect");
            return;
        }
    
        public static void fHaveReConnectMethod(long lLoginID, IntPtr pchDVRIP, long nDVRPort, uint dwUser)
        {
            System.Console.WriteLine("Reconnect success");
            return;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public class NET_DEVICEINFO
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
            public byte[] sSerialNumber;
            public byte byAlarmInPortNum;
            public byte byAlarmOutPortNum;
            public byte byDiskNum;
            public byte byDVRType;
            public byte byChanNum;
        }
    
        public static void Main()
        {
            fDisConnect fDisConnecthandler = fDisConnectMethod;
            fHaveReConnect fHaveReConnecthandler = fHaveReConnectMethod;
            NET_DEVICEINFO deviceinfo = new NET_DEVICEINFO();
            IntPtr iRet = new IntPtr(0);
            CLIENT_Init(fDisConnectMethod, 0);
            CLIENT_SetAutoReconnect(fHaveReConnecthandler, 0);
            lLogin = CLIENT_Login("192.168.1.198", 3112, "userid", "password", deviceinfo, iRet);
    
            int[] al = long2doubleInt(lLogin);
            if (al[0] <= 0)
                Console.WriteLine("Login device failed");
            else
            {
                Console.WriteLine("Login device successful");
                CLIENT_Logout(lLogin);
                CLIENT_Cleanup();
            }
        }
    }
    The error is thrown at the CLIENT_Logout method. Any assistance would be greatly appreciated.
    Last edited by BobS0327; September 19th, 2013 at 01:10 PM.

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: How to resolve a PInvokeStackImbalance was detected issue

    Is iRet returning an error?

  3. #3
    Join Date
    Apr 2004
    Posts
    102

    Re: How to resolve a PInvokeStackImbalance was detected issue

    Single stepping thru the code and using the variable watch window indicates that iRet is always zero. But as the documentation below indicates, as long as the function returns successfully, iRet would be meaningless.

    Calling CLIENT_Login always returns a good device id to me since I can use it to access the remote device. Thus, as the documentation indicates, iRet would be meaningless for me.

    CLIENT_Login
    registered user to device, when device terminal set user to multi-use(default user i.e. admin, not multi-use), so the account can register multiple times on device.

    LLONG CLIENT_Login(
    char *pchDVRIP,
    WORD wDVRPort,
    char *pchUserName,
    char *pchPassword,
    LPNET_DEVICEINFO lpDeviceInfo,
    int *error = 0
    );
    Parameters
    [in]pchDVRIP
    device IP
    [in]wDVRPort
    device port
    [in]pchUserName
    username
    [in]pchPassword
    user password
    [out]lpDeviceInfo
    device info, as output parameter
    [out]error

    (when function returns successfully, its value is meanless),return to login wrong code,as follows:
    wrong code meaning
    1 wrong password
    2 username not exist
    3 login overtime
    4 account already login
    5 accoung locked
    6 account on blacklist
    7 insufficient resource,system busy
    8 sub-connection failed
    9 main connection failed
    10 exceed max user connections

    Return Values
    failed return to 0,successful return to device ID,after successfully login operation on device may correspond to designated device via this value (device handle).

    Remarks
    after initialization may call the interface to register designated devices, if successful, device handle will be returned for call of related function.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured