【问题标题】:"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“运行时检查失败 #0 - ESP 的值未在函数调用中正确保存”从 C++ 代码成功 C# 回调后
【发布时间】:2010-11-30 17:09:24
【问题描述】:

我正在制作一个使用 GameSpy C 代码(GP 部分)的 C# 应用程序。 C 代码成功调用回调(即 C# 代码),但在回调完成后我立即收到此错误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 中的调用约定(这可能吗?)。还有其他想法吗?

【问题讨论】:

    标签: c# dll callback stack


    【解决方案1】:

    我自己出乎意料地解决了问题(经过 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
    );
    

    【讨论】:

      【解决方案2】:

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

       [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
      

      参考其他相关问题:Callback from C function - crash

      【讨论】:

        猜你喜欢
        • 2012-04-22
        • 2023-03-06
        • 2011-01-26
        • 2012-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多