[英]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.