none
C++ DLL 调用 C# 中回调函数在Debug下正常,Release下异常的问题 RRS feed

  • 问题

  • 原意:C#向DLL传入一个函数,DLL通过回调通知上层程序某些事件。

    DLL中定义:

     

    typedef int HTALKINSTANCE;
    typedef int (WINAPI *TalkConnectingCallBack)(HTALKINSTANCE tID, long iP, int port);
    

     

    DLL中调用:

     

    if(0 != m_cbConnecting(m_iID, 0, 0))
    {
    	TRACE("User Refused the client connect!");
    	return bReturn;
    }
    

     

    C#中定义:

     

    public delegate int DelegateTalkConnectingCallBack(int tID, int iP, int port);
    public static int OnConnecting(int tID, int iP, int port)
     {
       if (lbxMessage != null)
       {
          lbxMessage.Items.Add(string.Format("{0}  {1}", tID, "Client Try Connecting in ..."));
       }
    
       return 0;
    }
    

     

    现象:

    DLL调用该回调函数时,在SYSTEM.WINDOWS.FORMS.NI.DLL 模块中出现异常 0xC0000005 access violation

    仅当C#程序编译为Release版本时,才出现此异常;与DLL是DEBUG还是Release无关。

    取消C#项目Release版本的的Optimize code属性无法解决此问题。

    向C#项目的Release版本添加Define DEBUG constant属性后,会提示以下信息:

     

    File: i386\chkesp.c
    Line: 42
    
    The value of ESP was not properly saved across a function call. This is usually a result of calling 
    a function declared with one calling convention with a function pointer declared with a different calling convention.

     

    请教各位解决办法或可能的解决思路。谢谢!

    2010年8月20日 8:52

答案

  • [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.StdCall)]
    public delegate int TalkConnectingCallBack(int tID, int iP, int port);


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已建议为答案 mazhou 2010年8月23日 9:54
    • 已标记为答案 泉子 2010年8月24日 1:21
    2010年8月22日 16:42
    版主
  • 谢谢回复,此问题已解决。

    原因是C#向C++中传递了临时委托对象,显然这种传递不会增加对象的引用数,因此在Release程序中,这些对象经常很快就被回收掉,因此导致程序异常。

    另有疑问:直接启动DEBUG版本的程序或从IDE调试时,垃圾回收会被限制么?

    • 已标记为答案 泉子 2010年8月24日 1:21
    2010年8月24日 1:21

全部回复

  • [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.StdCall)]
    public delegate int TalkConnectingCallBack(int tID, int iP, int port);


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已建议为答案 mazhou 2010年8月23日 9:54
    • 已标记为答案 泉子 2010年8月24日 1:21
    2010年8月22日 16:42
    版主
  • 谢谢回复,此问题已解决。

    原因是C#向C++中传递了临时委托对象,显然这种传递不会增加对象的引用数,因此在Release程序中,这些对象经常很快就被回收掉,因此导致程序异常。

    另有疑问:直接启动DEBUG版本的程序或从IDE调试时,垃圾回收会被限制么?

    • 已标记为答案 泉子 2010年8月24日 1:21
    2010年8月24日 1:21
  • 谢谢回复,此问题已解决。

    原因是C#向C++中传递了临时委托对象,显然这种传递不会增加对象的引用数,因此在Release程序中,这些对象经常很快就被回收掉,因此导致程序异常。

    另有疑问:直接启动DEBUG版本的程序或从IDE调试时,垃圾回收会被限制么?

    请问你是怎么解决的?如何让其不是临时委托对象?
    2012年11月7日 11:00