Brandon Richmon
Brandon Richmon

Reputation: 3

Storing a function pointer as a member within a class

I created this account to ask a question because I'm pretty lost right now and I couldn't find an answer. I'm not sure if what I'm trying to do is even possible, or perhaps I'm taking an incorrect approach.

I'm writing a windows socket wrapper class for asynchronous sockets, mostly so I never have to write this code again, and I'm trying to store a function pointer as a member variable inside my netcode class that points to a windows event handler that's called inside the application's normal win32 message pump that points elsewhere. Basically, I'm trying to create a programmer-defined callback function so that when I compile this netcode class into a .dll I never have to touch it again.

As a clarification, what I'm trying to do is, for example, write the event handler for WM_SOCKET (which is a windows message I have defined) somewhere other than inside the network code class (so it can be portable to different win32/C++ projects) and outside of the main win32 message pump (so my WndProc() doesn't become absolutely massive).

I don't even know what to search for, but all of the information I'm finding is about creating a pointer to a member function or a member of a template, which isn't what I want.

Here's the code I've already tried to write (only the relevant bits), which is what is giving me problems. I'm probably royally screwing something up here.

//// 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);
}

I'd be really grateful for some help, here. I totally have no clue why this isn't working.

The errors I receive are:

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

If you need any better explanation, because I've likely explained this problem poorly, please don't hesitate to ask.

I'm using Visual Studio 2010, so I don't think I can use C++/11 features like std::function.

Upvotes: 0

Views: 350

Answers (3)

Drop
Drop

Reputation: 13003

  1. Exclude arguments names from function pointer declaration
  2. Use typedef to make code cleaner

    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. Prefer to use STL facilities to naked pointers: std::function of boost::function

    typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr;
    

Upvotes: 4

Nikhil
Nikhil

Reputation: 2308

Here is my suspicion. I think the way you've declared the function argument SocketFunction for registerSocketFunction is wrong.

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

should be,

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

I ran a similar test on GCC, and it threw a similar error, so this might be your problem.

Upvotes: 1

nio
nio

Reputation: 5289

You have to enclose the function pointer name in brackets like this: void (*SocketFunction)(...) So instead of your method declaration:

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

You have to write:

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

Also rewrite your method body to this:

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

Next thing, i think your HandleEvents is unfinished yet, you have a syntax error there, i think you wanted to call the function behind the pointer.

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

Upvotes: 2

Related Questions