“运行时检查失败#0 - ESP的值未正确保存跨函数调用”从C ++代码成功的C#后回调(“Ru

2019-07-19 03:13发布

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


    // 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调用约定(这可能吗?)。 任何其他的想法?

Answer 1:

检查您使用的调用约定。

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]

参考其他相关的问题: 回调从C函数-崩溃



Answer 2:

问题解决了意外我自己(5小时后google搜索)。 我怀疑是错误的调用约定了,但我不知道如何正确地打开它。 我在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
);


文章来源: “Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call” after successful C# callback from the C++ code