I have created ac# wrapper for a c++ dll,and I don't have the source code of the 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. 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
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
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
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
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
.
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
Call this before you call WiScn_Run
and then in 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#. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.