Сбой функции обратного вызова C на объекте pascal - PullRequest
0 голосов
/ 19 сентября 2018

Я создаю C dll, как показано ниже.

#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
    /* fun accept an argument status_callback which is a function pointer*/
    TEST_API void fun(void(*status_callback)(int));
#ifdef __cplusplus
}
#endif

, и fun реализован так:

void fun(void(*status_callback)(int)) {
   status_callback(0);
}

При использовании этой dll для объекта pascal с delphi xe, как показано ниже, япроизошел сбой с нарушением доступа по адресу функции обратного вызова

type
 TStatusCallBack = procedure( Value: Integer ); stdcall;
 T_fun = procedure(cb : TStatusCallback );

procedure BCallBack( Value: Integer ); stdcall;
begin
   BStatus := value;
end;

begin
 _fun(BCallBack);
end;

Код реализации:

DLLHandle := LoadLibrary( ‘mylib.dll’ );
if (DLLHandle > HDLL_ERROR) then
begin
  _fun := T_fun(GetProcAddress( DLLHandle, 'fun');
end;

В чем проблема?Поскольку я новичок в C любые комментарии ??

1 Ответ

0 голосов
/ 19 сентября 2018

Нам не хватает важных деталей.Мы не можем видеть реализацию fun на стороне C ++, и мы не можем видеть, как вы объявили _fun на стороне Delphi.

Однако есть одна ошибка, которую мы можем видеть.Соглашение о вызове для обратного вызова не совпадает.Код C ++ определяет обратный вызов как __cdecl.Вам нужно использовать cdecl для сопоставления на стороне Delphi, а не stdcall.

Аналогично, я ожидаю, что ваш код Delphi неправильно определяет соглашение о вызовах для _fun.Опять же, это должно быть cdecl, но в сообщении об ошибке указывается, что ваше объявление действительно register.

В итоге внесите следующие изменения в ваш код Delphi:

  • Объявите обратный вызовтип функции как cdecl.
  • Объявить функцию, которая реализует обратный вызов как cdecl.
  • Объявить импорт fun как cdecl.

Глядя на ваше редактирование, ваша ошибка проверки возвращаемого значения LoadLibrary неверна.Ошибка указывается возвращаемым значением, равным нулю.Сравните на равенство с нулем, чтобы проверить наличие ошибок.

Вы также не можете проверить ошибки при вызове GetProcAddress.Вам нужно обработать случай, когда возвращается nil.Опять же, это может привести к ошибке во время выполнения с вашим кодом, как написано.

И код в вашем редакторе показывает, что все мои догадки были верны.Решение как подробно описано в пунктах выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...