1
votes

Anyone know how i fix this error?

ERROR:

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

I am using P/Invoke to call a native code from a managed code. Native code is being imported via dynamic link libraries.

Steps are

  1. Locating .dll containing these function.
  2. Loading .dll into memory
  3. Locating the address of function in memory
  4. Transforming this memory representation of object to a data format (marshalling)

DLL has a function with declaration

long    __stdcall Connect (long,long,long,long,long,long,long,long);`

In my application i created a delegate

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate long delConnect(long a, long b, long c, long d, long e, long f, long g, long h);`

Then i created a class for loading dll and locating address of function in memory

`static class NativeMethods { [DllImport("kernel32.dll")] public static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);


    [DllImport("kernel32.dll")]
    public static extern bool FreeLibrary(IntPtr hModule);
}`

Now when i am trying to use the function then i am getting error

IntPtr pDll = NativeMethods.LoadLibrary("serial.dll");
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "_Connect@32");
delConnect connect = (delConnect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(delConnect)); 
long check = connect(1, 0, 12, 9600, 0, 0, 8, 0);
bool result = NativeMethods.FreeLibrary(pDll);`

I have used "_Connect@32" instead of "Connect" in function name parameters of GetProcAddress method, because of name mangling.

When i am debugging i get this error at line containing statement

long check = connect(1, 0, 12, 9600, 0, 0, 8, 0);

2

2 Answers

2
votes

The C/C++ long is 32 bit in Windows, so an int in .net. Try changing it (on Unix it's more like an IntPtr)

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private delegate int delConnect(int a, int b, int c, int d, int e, int f, int g, int h);

And perhaps instead of StdCall try Cdecl:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 

For the DllImport of Windows API you should use

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]

So that if possible .NET uses the Unicode variant, and not the Ansi variant.

0
votes

Is there a reason you're using LoadLibrary() rather than just PInvoking directly?

What happens if you try this instead:

[DllImport("serial.dll", EntryPoint = "_Connect@32", CallingConvention = CallingConvention.StdCall)]
static extern int DelConnect(int a, int b, int c, int d, int e, int f, int g, int h);

(Note C# int == C++ long, normally)