Как делегат должен быть возвращен для неуправляемого кода при вызове из обратного вызова? - PullRequest
0 голосов
/ 03 февраля 2011

У меня есть ситуация, когда я вхожу в неуправляемый код и выхожу из него, и я думаю, что моя методология заставляет меня получить «FatalExecutionEngineError».В частности, у меня есть обратный вызов C # («X»), который возвращает другой обратный вызов («Y») в C #, где X и Y вызываются неуправляемым кодом C ++ (который вызывается C #).Ошибка выдается при возврате из обратного вызова Y.


Операторы импорта Dll:

[DllImport ("SearchDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe bool Dll_Search_Text (..., delegate_add_result Fn);

Неуправляемый код C:

extern "C" {
__declspec(dllexport) bool Dll_Search_Text (..., bool (*Add_Result (int, int)) (int, int, int)) {
    bool (*Add_Result_Word) (int, int, int);
    bool Add_Word_Ret;

    ...    
    Add_Result_Word = Add_Result ([int param], [int param]);
    if (0 == Add_Result_Word) return false;
    ...

        for (Itr=Set->begin (); Itr != Set->end (); Itr++) {
            ...
            Add_Word_Ret = Add_Result_Word ([int param], [int param], [int param]);   
            }
        }

    return true;
    }
}

Определения делегата:

public delegate bool delegate_add_result_word (int A, int B, int C);
public delegate delegate_add_result_word delegate_add_result (int D, int E);

Сообщение об ошибке:

"Managed Debugging Assistant 'FatalExecutionEngineError' has detected a
problem in 'C:\Neuric\bin\Search.exe'. Additional Information: The 
runtime has encountered a fatal error. The address of the error was
at 0x6ea2ceca, on thread 0x744. The error code is 0xc0000005. This 
error may be a bug in the CLR or in the unsafe or non-verifiable 
portions of user code. Common sources of this bug include user marshaling
errors for COM-interop or PInvoke, which may corrupt the stack."

Код работает некоторое время (и работал отлично, прежде чем я добавил вложенныйобратные вызовы), но выдает это исключение в остальное время.

Ответы [ 2 ]

3 голосов
/ 03 февраля 2011

Делегаты обычно используют fastcall.Но указатели на функции в стиле c используют cdecl.Пометьте своего делегата атрибутом UnamangedFuntionPointer.

0 голосов
/ 03 февраля 2011

Я не уверен в точно , что вы делаете, но есть две причины, о которых я могу подумать. Я предполагаю, что вы преобразовали делегат в указатель на функцию. Тогда ...

  • Вы должны убедиться, что объект делегата не является сборщиком мусора. GC не видит указатель на вашу функцию, поэтому он очистит делегат без промедления. В пространстве имен msclr есть несколько дескрипторов-контейнеров дескрипторов, но если вы имеете дело со сложным сценарием, вам может потребоваться вручную выделить GCHandle. Конечно, вы уже можете это делать; -).
  • Кроме того, вы должны убедиться, что ссылка на объект, контролируемый ГХ, не перемещается при обращении к нему. pin_ptr - это один из способов сделать это локально, но вы звучите так, как будто передаете вещи сложным образом, поэтому это может означать, что вам нужно вручную закрепить объект с помощью GCHandle.Alloc(..., GCHandleType.Pinned)
...