c вызов нестатической функции из статической функции

#c #windows

#c #Windows

Вопрос:

При попытке вызвать нестатическую функцию возникает ошибка нарушения доступа.

мой .h файл выглядит следующим образом.

 class World
{
public:
    World();
    virtual ~World();
    static void CALLBACK DispatchCallback(
        SIMCONNECT_RECV *pData,
        DWORD cbData,
        void *pContext
    );
    void Process(SIMCONNECT_RECV *pData, DWORD cbData);
    virtual void frameEvent();
    virtual void init();
};
  

Теперь в моем .cpp-файле функция init() вызывает функцию, которая возвращает данные в мою функцию обратного вызова.

 SimConnect_CallDispatch(hSimConnect, DispatchCallback, NULL);
  

Которая отправляет данные в DisPatchCallback функцию.

В этой функции находится следующий код:

 void CALLBACK World::DispatchCallback(
    SIMCONNECT_RECV *pData,
    DWORD cbData,
    void *pContext)
{
    World *pThis = reinterpret_cast<World*>(pContext);
    pThis->Process(pData, cbData);
}
  

эта функция является статической функцией, которая создает мировой объект для вызова функции процесса.

Это работает, но прерывается в строке, где требуется получить доступ к функции frameEvent .

 void World::Process(SIMCONNECT_RECV *pData, DWORD cbData)
{
    HRESULT hr;

    switch(pData->dwID)
    {
    case SIMCONNECT_RECV_ID_EVENT_FRAME:
        frameEvent(); //it breaks here frameEvent is a non static function
        break;
    }
}
  

Местоположение чтения 0x00000000 с нарушением доступа.

Может кто-нибудь указать мне правильное направление для решения этой проблемы.?

Если вам интересно, я пишу плагин для Microsoft Flight Simulator X.

Я пытаюсь реализовать simconnect.h oo-способом. Msdn показывает пример, который я пытаюсь реализовать.

 class CName
{
    void Dispatch();
    static void DispatchCallback(
        SIMCONNECT_RECV *pData,
        DWORD cbData,
        void *pContext
    );
    void Process(SIMCONNECT_RECV *pData, DWORD cbData);

    HANDLE hSimConnect; // use SimConnect_Open to set this value.
};

void CName::Dispatch()
{
    ::SimConnect_Dispatch(hSimConnect, amp;CName;::DispatchCallback, this);
}

// static function
void CName::DispatchCallback(
    SIMCONNECT_RECV *pData,
    DWORD cbData,
    void *pContext)
{
    CName *pThis = reinterpret_cast<CName*>(pContext);
    pThis->Process(pData, cbData);
}

void CName::Process(SIMCONNECT_RECV *pData, DWORD cbData)
{
    // do processing of SimConnect data
}
  

Надеюсь, я дал достаточно информации.

Комментарии:

1. Чего вы пытаетесь достичь с помощью статических функций с контекстом? И, в общем, использование casts таким образом указывает на плохое проектирование…

2. @Griwes: на самом деле это очень распространенный шаблон при написании кода на C с использованием C API-интерфейсов — вы передаете его в this качестве параметра контекста вместе с static функцией обратного вызова, которая перенаправляет обратный вызов в метод класса объекта. Он используется с оконными процедурами, потоковыми процедурами, обратными вызовами библиотеки и т. Д.

Ответ №1:

Вы передаете NULL в качестве параметра контекста SimConnect_CallDispatch , поэтому ваш обратный вызов понятия не имеет, какой World объект вызывать Process — как это возможно, если вы не указываете это? Измените вызов на передачу в this качестве параметра контекста, как в примере:

 SimConnect_CallDispatch(hSimConnect, DispatchCallback, this);
  

Комментарии:

1. Спасибо, мне немного стыдно, что я упустил из виду, что это так очевидно!

Ответ №2:

Ваше использование:

 SimConnect_CallDispatch(hSimConnect, DispatchCallback, NULL);
  

кажется очень подозрительным. Что NULL означает параметр при вызове этой функции? Это так pContext ?

Ответ №3:

Он прерывается, потому this что равен NULL .

Проверьте эту часть вашего кода:

 World *pThis = reinterpret_cast<World*>(pContext);
pThis->Process(pData, cbData);
  

Если reinterpret_cast сбой получает значение NULL — оно возвращает значение NULL, и вы его не проверяете.

Комментарии:

1. reinterpret_cast не может произойти «сбой» — либо он компилируется, либо нет. Если pThis равно null , то также pContext должно быть null .