PInvoke changes  
Author Message
LoveMeSomeCode





PostPosted: Visual C# General, PInvoke changes Top

I got this message on my recently upgraded 2005 project :

A call to PInvoke function ....::SendMessage' 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.

My external signature is:
DllImport("user32.dll", EntryPoint="SendMessageA")]
public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr wParam, object lParam);

I looked into this and found some sites indicating that I could have problems with 64-bit code if I used an object for lParam or anything but IntPrt for the return type.

The question I have is: I'm not building 64-bit code(that I know of). So why am I getting this exception I'm getting other oddities related to ToString() conversion and am starting to wonder if I'm missing a 64-bit setting somewhere. I just used the project upgrade wizard to take it from 2003, and it said everything worked fine. The code does build and run fine until it hits these exceptions.

Any help would be great,

Nick


Visual C#1  
 
 
Peter Ritchie





PostPosted: Visual C# General, PInvoke changes Top

SendMessage can't possibly do anything with a .NET object. I would suggest changing your SendMessage declaration to reflect the use of opaque types: public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam). I'm not sure what the CLR will do when marshaling an object when you've declared SendMessage as taking an object argument. You may find you'll have to pin your object to send it as an IntPtr parameter.

 
 
RizwanSharp





PostPosted: Visual C# General, PInvoke changes Top

Try one of these, if the help:

static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);

static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, String lParam);

static extern void SendMessage(HandleRef hWnd, uint msg, IntPtr wParam, ref RECT lParam);

static extern IntPtr SendMessage(HandleRef hWnd, uint msg, IntPtr wParam, ref POINT lParam);

Reference:

http://pinvoke.net/search.aspx search=SendMessage&namespace=[All]

Best of Luck.

Rizwan



 
 
LoveMeSomeCode





PostPosted: Visual C# General, PInvoke changes Top


Sorry, I wasn't being clear enough. I know I need to change the signature, and I already changed it. The 2005 code works now. My question was why I had to change it. This code has been working for a long time in 2003. I'm still building 32-bit binaries as far as I know, so the Win32 calls should be the same. Was I unbalancing the stack before and just not getting an exception

 
 
Peter Ritchie





PostPosted: Visual C# General, PInvoke changes Top

In Visual Studio 2005 they introduced debugging assistants. One of these assistants looks at the stack pointer before and after a PInvoke call. Defining a DLL entry point .NET is completely disconnected from the actual code that gets called. That code pulls parameters off the stack one at a time changing the stack pointer by the size of the parameter it takes off. PInvoking code does the opposite, putting things on the stack increasing the stack pointer by the size of the parameter it puts on. If those two processes are not identical the stack pointer will not be the same upon return of the PInvoked function--the pushes and the pops were not balanced. This means the PInvoke definition did not define the arguments of the function properly and random bad things will happen. The pinvoke stack imbalance debugging assistant is meant to catch these errors.