Хранение указателя на функцию в качестве члена в классе

0

Я создал эту учетную запись, чтобы задать вопрос, потому что сейчас я довольно потерян, и я не смог найти ответ. Я не уверен, что то, что я пытаюсь сделать, даже возможно, или, возможно, я использую неправильный подход.

Я пишу класс оболочки стека Windows для асинхронных сокетов, в основном, поэтому мне больше не нужно писать этот код, и я пытаюсь сохранить указатель на функцию как переменную-член внутри моего класса netcode, которая указывает на обработчик событий Windows, который вызванный внутри стандартного насоса сообщений win32 приложения, который указывает в другом месте. В принципе, я пытаюсь создать определенную программистом функцию обратного вызова, так что, когда я скомпилирую этот класс netcode в.dll, мне больше не придется его трогать.

Как пояснение, я пытаюсь, например, написать обработчик событий для WM_SOCKET (который является сообщением Windows, которое я определил) где-то, кроме внутри класса сетевого кода (поэтому он может быть переносимым для разных win32/C++) и за пределами основного насоса сообщений win32 (так что мой WndProc() не становится абсолютно массивным).

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

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

//// Sockets.h
class NetworkConnection
{
private:
    void (*WMSocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

public:
    void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));
};

//// Sockets.cpp
#include "Sockets.h"

void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))
{
    WMSocketFunction = SocketFunction;
};

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    WMSocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
}

//// Application.cpp
void SocketEventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Do socket stuff here
};

int SetupApp()
{
    NetworkConnection NetConnection;
    NetConnection.registerSocketFunction(&SocketEventHandler);
    return 0;
}

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {

    case WM_SOCKET:
        {
            NetConnection.HandleEvents(hwnd, msg, wParam, lParam);
            break;
        }

    case WM_DESTROY:
        {
            ReleaseDevices();
            break;
        }
    case WM_KEYDOWN:
        {
#ifdef _DEBUG
            if (lParam == VK_ESCAPE)
                PostQuitMessage(0);
#endif
        }
    }
    return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

Я был бы очень благодарен за помощь, здесь. Я совершенно не понимаю, почему это не работает.

Я получаю следующие ошибки:

Error   1   error C2440: '=' : cannot convert from 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)'    sockets.cpp (in function registerSocketFunction)
Error   2   error C2275: 'HWND' : illegal use of this type as an expression     sockets.cpp (in function HandleEvents)
Error   3   error C2146: syntax error : missing ')' before identifier 'hwnd'    sockets.cpp (in function HandleEvents)
Error   4   error C2059: syntax error : ')'    sockets.cpp (in function HandleEvents)
Error   8   error C2664: 'NetworkConnection::registerSocketFunction' : cannot convert parameter 1 from 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)'    application.cpp

Если вам нужно какое-то лучшее объяснение, потому что я, вероятно, плохо объяснил эту проблему, пожалуйста, не стесняйтесь спрашивать.

Я использую Visual Studio 2010, поэтому я не думаю, что могу использовать функции C++/11, такие как std :: function.

Теги:
class
pointers
winapi

3 ответа

2
Лучший ответ

Вы должны заключить имя указателя функции в скобки следующим образом: void (*SocketFunction)(...) Итак, вместо объявления вашего метода:

void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));

Вы должны написать:

void registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam));

Также перепишите тело метода следующим образом:

void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND, UINT, WPARAM, LPARAM))
{
    WMSocketFunction = SocketFunction;
};

Следующая вещь, я думаю, что ваш HandleEvents еще не закончен, у вас там синтаксическая ошибка, я думаю, вы хотели вызвать функцию за указателем.

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    WMSocketFunction(hwnd,msg,wParam,lParam);
}
  • 0
    О мой Это сделал это! Редактировать: хит введите преждевременно. Большое спасибо за то, что поймали мои ошибки! Я бы проголосовал за тебя, если бы у меня была репутация сделать это. Я собирался выбросить это и попробовать другой подход,
  • 0
    Не должен вызывать функцию через указатель в виде (*WMSocketFunction)(hwnd,msg,wParam,lParam); ?
Показать ещё 1 комментарий
4
  1. Исключить имена аргументов из объявления указателя функции
  2. Использовать typedef для очистки кода

    typedef void(*WMSocketFunction_Ptr)(HWND, UINT, WPARAM, LPARAM);
    
    class NetworkConnection
    {
    private:
        WMSocketFunction_Ptr WMSocketFunction;
    
    public:
        void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
        void registerSocketFunction(WMSocketFunction_Ptr SocketFunction);
    };
    
    void NetworkConnection::registerSocketFunction(WMSocketFunction_Ptr SocketFunction)
    {
        WMSocketFunction = SocketFunction;
    };
    
  3. Предпочитаете использовать объекты STL для голой указатели: std :: function boost :: function

    typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr;
    
  • 0
    Если я могу спросить, есть ли какие-либо преимущества в использовании средств STL в этом примере? Какой будет синтаксис? РЕДАКТИРОВАТЬ: Кроме того, я не думаю, что я могу использовать это, так как Visual Studio 2010 не хватает хорошей поддержки C ++ / 11, верно?
  • 1
    std :: function более читабельна, более безопасна и поэтому менее подвержена ошибкам. Но главное преимущество в том, что он более гибкий: он позволяет связывать не только функции, но и выражения std :: bind, объекты функций и лямбда-выражения. Если я правильно помню, VS2010 с некоторым пакетом обновления поддерживает std::tr1::function . Если ваш компилятор не поддерживает его, вы можете использовать boost :: function.
Показать ещё 1 комментарий
1

Вот мое подозрение. Я думаю, что способ, которым вы объявили аргумент функции SocketFunction для registerSocketFunction, неверен.

void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))

должно быть,

void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))

Я проверил аналогичный тест на GCC, и он выбросил аналогичную ошибку, так что это может быть вашей проблемой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню