2009-09-23 62 views
0

我在製作一個使用GameSpy C代碼的C#應用​​程序(GP部分)。 C代碼成功地調用了回調函數(即C#代碼),但在回調完成後我收到了錯誤Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call。我做了一個DLL出的C代碼,像這樣:從C++代碼成功執行C#回調後,「運行時檢查失敗#0 - ESP的值未在函數調用中正確保存」


    // 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中調用約定(這可能嗎?)。任何其他想法?

回答

3

問題解決了意外我自己(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 
); 
相關問題