簡體   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