简体   繁体   English

从C#调用C ++委托超出内存异常

[英]Calling c++ delegate from c# out of memory exception

I have created ac# wrapper for a c++ dll,and I don't have the source code of the c++ dll. 我已经为c ++ dll创建了ac#包装程序,但是我没有c ++ dll的源代码。 Now the c++ has a delegate function,I have created the delegate function in c# wrapper and provide it with the necessary parameters. 现在,c ++具有委托函数,我已经在c#包装器中创建了委托函数,并为其提供了必要的参数。 The issue that am facing is whenever the delegate function is complete I receive an out of memory exception and I have also discovered that the delegate uses a new thread. 面临的问题是,只要委托函数完成,我就会收到内存不足异常,并且我还发现委托使用了新线程。 I will demonstrate the code that I have below: 我将在下面演示我的代码:

1) C# wrapper 1)C#包装器

public struct WISCN_RUN_OPTS
{
    public uint Version;
    public WISCN_CALLBACK_CODELINE_DONE CodelineDoneCallback;
}


[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public delegate bool WISCN_CALLBACK_CODELINE_DONE(
    uint doc_index,
    uint user_data,
    uint codelines_count,
    WISCN_CODELINE[] codelines,ref
    WISCN_CODELINE_DOC_CTRL p_doc_ctrl);

[DllImport(@"wiscn.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
public static extern WISCN_ERROR WiScn_Run(_WISCN_HINST_STRUCT hinst, uint num_of_docs, ref uint p_docs_done, ref WISCN_RUN_OPTS p_opts);

2) C# windows application 2)C#Windows应用程序

private void ButtonProcessDocsWithOcr_Click(object sender, EventArgs e)
{
    var run_opts = new DllLoad.WISCN_RUN_OPTS
    {
        Version = DefineConstants.WISCN_STRUCT_VERSION_RUN_OPTS
        CodelineDoneCallback = DocDoneCallback;
    };

    //The callback delegate is called when this method is triggered
    WiScn_Run(hinst, 0, ref docNum, ref run_opts);
}

bool DocDoneCallback(uint doc_index, uint user_data,
    uint codelines_count,
    WISCN_CODELINE[] codelines,ref
    WISCN_CODELINE_DOC_CTRL p_doc_ctrl)
{
    return false;
}//After this line i receive the out of memory exception 
 // when it tries to resume ButtonProcessDocsWithOcr_Click event.

3) C++ wrapper header file 3)C ++包装程序头文件

typedef struct 
{
    DWORD   Version;
    WISCN_CALLBACK_CODELINE_DONE    CodelineDoneCallback;                                                              
}
WISCN_RUN_OPTS;

typedef BOOL (*WISCN_CALLBACK_CODELINE_DONE)(DWORD doc_index, 
    DWORD user_data, DWORD codelines_count, const WISCN_CODELINE codelines[],
    WISCN_CODELINE_DOC_CTRL *p_doc_ctrl);

typedef WISCN_ERROR (WISCN_API *WISCN_RUN)(WISCN_HINST hinst, DWORD num_of_docs, LPDWORD p_docs_done, const WISCN_RUN_OPTS *p_opts);

WISCN_ERROR WISCN_API WiScn_Run(WISCN_HINST hinst, DWORD num_of_docs, LPDWORD p_docs_done, const WISCN_RUN_OPTS *p_opts);

4) c++ sample 4)C ++示例

BOOL DocDoneCallback(DWORD doc_index, DWORD user_data, 
    DWORD codelines_count, const WISCN_CODELINE codelines[], 
     WISCN_CODELINE_DOC_CTRL *p_doc_ctrl)
{
    return FALSE;
}
void main()
{
    WISCN_RUN _WiScn_Run;
    WISCN_RUN_OPTS run_opts;
    _WiScn_Run = (WISCN_RUN)GetProcAddress(hmod, "WiScn_Run");
    run_opts.Version = WISCN_STRUCT_VERSION_RUN_OPTS;
    run_opts.DocDoneCallback = DocDoneCallback;
    _WiScn_Run(hinst, 0, NULL, &run_opts);
}

You mentioned that a new thread is created by the unmanaged code. 您提到了非托管代码创建了一个新线程。 It seems plausible to me that the callback is called in the context of the unmanaged thread. 在我看来,在非托管线程的上下文中调用回调是合理的。 Check that by calling GetCurrentThreadId . 通过调用GetCurrentThreadId检查。

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();

Call this before you call WiScn_Run and then in DocDoneCallback . 在调用WiScn_Run之前先调用此WiScn_Run ,然后再调用DocDoneCallback I hypothesise that you will discover that your callback runs in a different thread. 我假设您会发现您的回调在另一个线程中运行。

If I am right with this hunch then you can never call that library from C#. 如果我对这种预感是正确的,那么您永远无法从C#调用该库。 What you'd have to do would be to wrap the C++ code in a mixed mode C++/CLI wrapper so that you can implement your callback function in unmanaged code. 您要做的是将C ++代码包装在混合模式C ++ / CLI包装器中,以便可以在非托管代码中实现回调函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM