“运行时检查失败#0 – 从C ++代码成功进行C#回调后,ESP的值未在函数调用中正确保存”

我正在制作一个使用GameSpy C代码的C#应用​​程序(GP部分)。 C代码成功地调用了一个回调(它是C#代码),但是我得到了这个错误Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call在回调完成后Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call 。 我用C代码制作了一个DLL,如下所示:

 // GPCallback ///////////// __declspec(dllexport) typedef void (* GPCallback)( GPConnection * connection, void * arg, void * param ); // gpConnect //////////// __declspec(dllexport) GPResult gpConnect ( GPConnection * connection, const gsi_char nick[GP_NICK_LEN], const gsi_char email[GP_EMAIL_LEN], const gsi_char password[GP_PASSWORD_LEN], GPEnum firewall, GPEnum blocking, GPCallback callback, void * param ); 

C#就像这样调用它:

 unsafe public delegate void GPCallback( GPConnection * connection, //GPConnectResponseArg arg, IntPtr arg, IntPtr param ); [DllImport("saketestd.dll")] unsafe static extern GPResult gpConnect( GPConnection * connection, gsi_char nick, gsi_char email, gsi_char password, GPEnum firewall, GPEnum blocking, GPCallback callback, IntPtr param ); unsafe public bool gpConnectE() { bool ret = false; try { GPResult res; debug.AddLine(this.getMethodName() + ": " + "connection before connect: " + connection.ToString("x")); fixed (int* pconn = &connection) { res = gpConnect( pconn, this.NICK, this.EMAIL, this.PASSWORD, GPEnum.GP_NO_FIREWALL, GPEnum.GP_BLOCKING, new GPCallback(this.ConnectResponse), IntPtr.Zero ); } debug.AddLine(this.getMethodName() + ": " + "connection after connect: " + connection.ToString("x")); if (res != GPResult.GP_NO_ERROR) { debug.AddLine(this.getMethodName() + ": " + "failed: " + res); } else { debug.AddLine(this.getMethodName() + ": " + "OK"); ret = true; } } catch (Exception ex) { debug.Text += ex.ToString(); } return ret; } unsafe public void ConnectResponse( GPConnection * connection, //GPConnectResponseArg arg, IntPtr argPtr, IntPtr param ) { debug.AddLine(this.getMethodName() + " called with connection: " + (*connection).ToString("x")); GPConnectResponseArg arg; arg = (GPConnectResponseArg)Marshal.PtrToStructure(argPtr, typeof(GPConnectResponseArg)); if (arg.result == GPResult.GP_NO_ERROR) { debug.AddLine(this.getMethodName() + ": Connected to GP"); this.profileid = arg.profile; } else { debug.AddLine(this.getMethodName() + ": failed"); debug.AddLine(this.getMethodName() + ": result: " + arg.result); debug.AddLine(this.getMethodName() + ": profile: " + arg.profile); debug.AddLine(this.getMethodName() + ": uniquenick: " + arg.uniquenick); } } 

我相信我需要在回调中清除堆栈或更改DLL中的调用约定(可能吗?)。 还有其他想法吗?

检查您正在使用的调用约定。

  [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 

参考其他相关问题: 来自C函数的回调 – 崩溃

问题意外地解决了我自己(在谷歌上搜索5小时后)。 我已经怀疑错误的调用约定,但我不知道如何正确切换它。 我在这里建议的C代码中更改了它( http://computerarts.com.cn/dotnet-tech/1691/ ):

 // GPCallback ///////////// //__declspec(dllexport) typedef void (* GPCallback)( //typedef __declspec(dllexport) void (* GPCallback)( typedef void (_stdcall * GPCallback)( GPConnection * connection, void * arg, void * param );