Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Вызов функции C++ с указателем на функцию C# в качестве параметра

Автор вопроса: NirdeshОтветов: 1

У меня есть следующий код в Native C dll.

typedef void CallbackType( INT32 param1, INT32 param2 );

NATIVE_API void RegisterEventCallBack(CallbackType *callBackFunction);


//INT32 is defined as below:

typedef signed int          INT32, *PINT32;

Я должен вызвать этот метод из моего кода C#. Выполнив некоторые решения, доступные в stackflow, я попробовал это:

Декларация делегата:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackType(Int32 param1, Int32 param2);

Объявление импорта метода:

[DllImport("EtIPAdapter.dll")]
public static extern void RegisterEventCallBack([MarshalAs(UnmanagedType.FunctionPtr)]CallbackType callbackFunc);

Звонок:

RegisterEventCallBack(ReceivedData);

private static void ReceivedData(Int32 param1, Int32 param2)
{
    //Do something
}

Но это не работает, и я получаю следующую ошибку:

Вызов функции PInvoke "RegisterEventCallBack" разбалансировал стек. Вероятно, это связано с тем, что управляемая подпись PInvoke не соответствует неуправляемой целевой подписи. Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

Я также попытался передать указатель функции, который я получил, используя GetFunctionPointerFromDelegate(ReceivedDataDelegate). Но это также приводит к той же ошибке.

Ошибка указывает на несоответствие подписи, но я не вижу явного несоответствия подписи. Пожалуйста помоги.

  • Вы можете попробовать следующее объявление в ссылке: stackoverflow.com/a/9855516/2253250 также следует проверить правильность прототипа функции? nirsoft.net/utils/dll_export_viewer.html может использовать DllExport Viewer. Gencebay 09.04.2013
  • Как определяется макрос NATIVE_API? Я думаю, что проблема связана с вашим управляемым объявлением функции RegisterEventCallBack, а не с делегатом обратного вызова. Используете ли вы правильное соглашение о вызовах? Кажется странным, что RegisterEventCallBack будет использовать stdcall (по умолчанию для DllImport), когда его параметр обратного вызова использует cdecl. anton.burger 09.04.2013

c++functionpointersmarshalling

Ответы

Ответ 1 · рейтинг 1 · weismat

Пожалуйста, проверьте соглашение о вызовах при выполнении DLLImport - по умолчанию это Winapi / StdCall.
Также важно, чтобы вы сохраняли ссылку на свой делегат внутри управляемого кода в течение всего времени существования приложения, поскольку в противном случае сборщик мусора удалит ваш делегат через некоторое время, потому что сборщик мусора может подсчитывать ссылки только внутри управляемого кода. Обычно я сохраняю ссылку на делегат как на статическое свойство класса, который устанавливает делегат.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы