C ++ function call from C # - unbalanced stack

I have an unmanaged C ++ function with the following signature:

int function(char* param, int ret)

I am trying to call it from C #:

unsafe delegate int MyFunc(char* param, int ret);

...

int Module = LoadLibrary("fullpathToUnamanagedDll");
IntPtr pProc = GetProcAddress(Module, "functionName");
MyFunc func = (MyFunc)System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(pProc, typeof(MyFunc));

unsafe
{
    char* param = null;
    int ret = 0;
    int result = func(param, ret);
}

As far as I can tell from the old C ++ project specification, both null for param and 0 for ret are valid function inputs. When I try to call it, it seems to work, however, after exiting, I get the following error:

detected by PInvokeStackImbalance

The PInvoke function call '... :: Invoke' has an unbalanced stack. This is likely because the PInvoke managed signature does not match the unmanaged target signature. Ensure that the calling agreement and parameters of the PInvoke signature match the target unmanaged signature.

, ( ), . - , ?

+3
3

IIRC, . , IL Reflection.Emit.

:

protected static Type MakeDelegateType(Type returntype, List<Type> paramtypes)
{
  ModuleBuilder dynamicMod = ... ; // supply this

  TypeBuilder tb = dynamicMod.DefineType("delegate-maker" + Guid.NewGuid(), 
      TypeAttributes.Public | TypeAttributes.Sealed, typeof(MulticastDelegate));

  tb.DefineConstructor(MethodAttributes.RTSpecialName | 
       MethodAttributes.SpecialName | MethodAttributes.Public |
       MethodAttributes.HideBySig, CallingConventions.Standard,
       new Type[] { typeof(object), typeof(IntPtr) }). 
       SetImplementationFlags(MethodImplAttributes.Runtime);

  var inv = tb.DefineMethod("Invoke", MethodAttributes.Public | 
       MethodAttributes.Virtual | MethodAttributes.NewSlot | 
       MethodAttributes.HideBySig, 
       CallingConventions.Standard ,returntype,null, 
       new Type[] 
       { 
          // this is the important bit
          typeof(System.Runtime.CompilerServices.CallConvCdecl)
       }, 
       paramtypes.ToArray(), null, null);

  inv.SetImplementationFlags(MethodImplAttributes.Runtime);

  var t = tb.CreateType();
  return t;
}
+2

, , , , UnmanagedFunctionPointer , :

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
unsafe delegate int MyFunc(char* param, int ret);

MSDN:

, .

+7

, : # DLL , char * . , . , , - , .. .

, DLL , [] 2 , :

    private const string MYDLL = @"my.dll";

    [DllImport(MYDLL, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
    public static extern int DataBlockDownload([MarshalAs(UnmanagedType.U4)] int A, [MarshalAs(UnmanagedType.LPArray, SizeConst = 2048)] byte[] B, [MarshalAs(UnmanagedType.U4)] int C);

    // NOTE: The data block byte array is fixed at 2Kbyte long!!
public delegate int DDataBlockCallback([MarshalAs(UnmanagedType.U4)] int A, [MarshalAs(UnmanagedType.LPArray, SizeConst = 2048)] byte[] B, [MarshalAs(UnmanagedType.U4)] int C);

, , char, .

You do not say what you are doing with your char * data if it is included in your C ++ code as a parameter or C ++ code passes it back to the managed world. Read the C # ref and out keywords as ways to avoid the char * type and the unsafe modifier.

With a little Googling from this, you can figure it out.

-1
source

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


All Articles