PInvokeStackImbalance exception when using IntPtr in .NET 4? (Works in .NET 3.5)

Maybe a little question about the noob, but this is what has turned me on in the brine for the past few hours (or days) ...

I am calling a method from a DLL in my code in the .NET Framework 4.0

[DllImport("xeneth.dll")] public static extern ErrorCode XC_GetFrame(Int32 h, FrameType type, ulong ulFlags, IntPtr buff, uint size); 

and then using it here:

 if (XC_GetFrame(myCam, XC_GetFrameType(myCam), 0, IntPtr.Zero, (uint)fs) != ErrorCode.E_NO_FRAME) 

However, when I run this in .NET 4.0, I get a P / INVOKE error, however ... doing this in 3.5 does not cause this error. After I and another programmer switched the code, we seemed to put it on IntPtr, working differently on 4.0.

My application should run in .NET 4.0, as a couple of the functions required by the application are only available in 4.0 ...

Is there anything that I may forget or just forget to turn on?

Any thoughts are greatly appreciated!

Tom

Update:

Basic declaration:

 virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, void *buffer, unsigned int size) 

Error: PInvoke function call "DLLTest! DLLTest.Form1 :: XC_GetFrameType" has an unbalanced stack. This is likely due to the fact that the PInvoke managed signature does not match the unmanaged target signature. Verify that the calling agreement and PInvoke signature settings match the target unmanaged signature.

+4
source share
3 answers

Two common reasons for this:

  • Call mismatch. Your C # code uses the default value of stdcall . Perhaps native code uses cdecl . Try adding CallingConvention=CallingConvention.Cdecl to the DllImport attribute.
  • Inconsistency of parameter lists (see below).

Do not forget that your code is in order because .net 3.5 does not cause this error. Error detection in .net 4 is better, so you only see errors there. But your code is broken in all versions of .net.


Native definition for your C ++ virtual method:

 virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, void * buffer, unsigned int size); 

It looks like you are passing the object pointer as the first parameter in the pinvoke call. I think this might work, although I don’t know enough about how virtual functions are handled during export to find out if this is a problem. Presumably, you exported a simple C function to create objects.

Another problem I see is that in Windows C / C ++ long is 32 bits. C # long is 64 bits. This means that the correct declaration for ulFlags is uint in C # code.

+8
source

At the top of my head did you check the bitt of both projects? You will get errors if one of them is 64-bit and the other 32-bit. Please note that in a recent version, the default for C # projects changed from any processor to x86. This does not matter for x86, but on x64 it is significant.

In addition, you should include as much error text as possible, since censorship to protect private information is great, but the error number and text can be very useful. In addition, when working with extern it is useful to include both definitions of any struct types to make sure they are equivalent. (Another common problem).

+3
source

Maybe the best question is why it worked before. In the statement you indicated:

virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, void * buffer, unsigned int size)

has .NET types corresponding to: FrameType, uint, IntPtr, uint .

On Windows, the unsigned long is a 32-bit type, and in C # ulong is a 64-bit type.

+1
source

Source: https://habr.com/ru/post/1403756/


All Articles