从回调调用时,如何为非托管代码返回委托?

时间:2011-02-03 16:18:08

标签: c# c++ delegates unmanaged dllimport

我有一种情况,我正在进出un /托管代码,我认为我的方法导致我得到一个“FatalExecutionEngineError”。具体来说,我有一个C#回调(“X”),它将另一个回调(“Y”)返回到C#,其中X和Y都由非托管C ++代码(由C#调用)调用。从回调Y返回时抛出错误。


Dll导入语句:

[DllImport ("SearchDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe bool Dll_Search_Text (..., delegate_add_result Fn);

非托管C代码:

extern "C" {
__declspec(dllexport) bool Dll_Search_Text (..., bool (*Add_Result (int, int)) (int, int, int)) {
    bool (*Add_Result_Word) (int, int, int);
    bool Add_Word_Ret;

    ...    
    Add_Result_Word = Add_Result ([int param], [int param]);
    if (0 == Add_Result_Word) return false;
    ...

        for (Itr=Set->begin (); Itr != Set->end (); Itr++) {
            ...
            Add_Word_Ret = Add_Result_Word ([int param], [int param], [int param]);   
            }
        }

    return true;
    }
}

代表定义:

public delegate bool delegate_add_result_word (int A, int B, int C);
public delegate delegate_add_result_word delegate_add_result (int D, int E);

错误消息:

"Managed Debugging Assistant 'FatalExecutionEngineError' has detected a
problem in 'C:\Neuric\bin\Search.exe'. Additional Information: The 
runtime has encountered a fatal error. The address of the error was
at 0x6ea2ceca, on thread 0x744. The error code is 0xc0000005. This 
error may be a bug in the CLR or in the unsafe or non-verifiable 
portions of user code. Common sources of this bug include user marshaling
errors for COM-interop or PInvoke, which may corrupt the stack."

代码在某些时候工作(并且在我添加嵌套回调之前工作得很好),但在其余时间抛出此异常。

2 个答案:

答案 0 :(得分:3)

代表们通常使用fastcall。但是c样式函数指针使用cdecl。使用UnamangedFuntionPointer属性标记您的委托。

答案 1 :(得分:0)

我不确定完全你正在做什么,但我可以想到两个原因。我假设你已经将委托转换为函数指针。然后...

  • 您必须确保委托对象不是垃圾回收。 GC没有看到你的函数指针,所以它会清理委托代码。在命名空间msclr中有一些句柄句柄容器,但如果您正在处理复杂场景,则可能需要手动分配GCHandle。当然,你可能已经这样做了; - )。
  • 您必须进一步确保在访问GC控制对象时不会移动该对象。 pin_ptr是在本地执行此操作的一种方法,但您听起来像是以复杂的方式传递事物,因此这可能意味着您需要手动固定对象,GCHandle.Alloc(..., GCHandleType.Pinned)