繁体   English   中英

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

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

我已经为c ++ dll创建了ac#包装程序,但是我没有c ++ dll的源代码。 现在,c ++具有委托函数,我已经在c#包装器中创建了委托函数,并为其提供了必要的参数。 面临的问题是,只要委托函数完成,我就会收到内存不足异常,并且我还发现委托使用了新线程。 我将在下面演示我的代码:

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应用程序

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 ++包装程序头文件

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 ++示例

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);
}

您提到了非托管代码创建了一个新线程。 在我看来,在非托管线程的上下文中调用回调是合理的。 通过调用GetCurrentThreadId检查。

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

在调用WiScn_Run之前先调用此WiScn_Run ,然后再调用DocDoneCallback 我假设您会发现您的回调在另一个线程中运行。

如果我对这种预感是正确的,那么您永远无法从C#调用该库。 您要做的是将C ++代码包装在混合模式C ++ / CLI包装器中,以便可以在非托管代码中实现回调函数。

暂无
暂无

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

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