James Moore
James Moore

Reputation: 447

Pass a non-static function pointer to another class?

I have two classes, Win32 and Engine. I'm trying to pass my WindowProc function from my Engine class to the Win32 class. I know that the typedef WNDPROC is declared as:

typedef LRESULT(CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);

My Win32 header is declared as:

// Win32.h
#include <Windows.h>

class Win32
{
    public:
        Win32() {};
        ~Win32() {};

        void Initialize(WNDPROC);

    private:
        // Route messages to non static WindowProc that is declared in Engine class.
        static LRESULT CALLBACK MessageRouter(HWND, UINT, WPARAM, LPARAM);
};

And my Engine class is declared as:

// Engine.h
#include "Win32.h"

class Engine
{
    public:
        Engine() {};
        ~Engine() {};

        void Initialize();

    private:
        LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

        Win32* m_win32;
};


// Engine.cpp
#include "Engine.h"

void Engine::Initialize()
{
    m_win32 = new Win32;
    m_win32->Initialize(&WindowProc);  // How can I pass this function without making
                                       // it static or global.
}

My Win32 class already has a static MessageRouter that is given to WNDCLASSEX. So my question is, how do I pass the Engine::WindowProc function to class Win32 without declaring it static or global?

Upvotes: 1

Views: 754

Answers (2)

Chris Cooper
Chris Cooper

Reputation: 432

For the sake of completeness, there is a way to do it with language constructs as well. This implementation uses pointer to member functions:

// Win32.h
#include <Windows.h>

class Engine;

class Win32
{
    public:
        Win32() {};
        ~Win32() {};

        void Initialize(LRESULT(CALLBACK Engine::* function)(HWND, UINT, WPARAM, LPARAM));

    private:
        // Route messages to non static WindowProc that is declared in Engine class.
        static LRESULT CALLBACK MessageRouter(HWND, UINT, WPARAM, LPARAM);
};

class Engine
{
    public:
        Engine() {};
        ~Engine() {};

        void Initialize();

    private:
        LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

        Win32* m_win32;
};

void Engine::Initialize()
{
    m_win32 = new Win32;
    m_win32->Initialize(&Engine::WindowProc);  // How can I pass this function without making
                                               // it static or global.
}

int main(void)
{
    Engine engine;

    engine.Initialize();

    return 0;
}

Upvotes: 1

Andy Prowl
Andy Prowl

Reputation: 126432

You can use std::function and std::bind() (in C++11), or boost::function boost::bind() (in C++03). The two are pretty much equivalent in functionality, so I will show the use of std::bind().

Here is how you could define a type alias called WNDPROC_FXN based on std::function:

typedef std::function<LRESULT CALLBACK (HWND, UINT, WPARAM, LPARAM)> WNDPROC_FXN;

This is how you would use it in your Win32 class:

class Win32
{
public:
    Win32() {};
    ~Win32() {};

    void Initialize(WNDPROC_FXN);
//                  ^^^^^^^^^^^

private:
    // Route messages to non static WindowProc that is declared in Engine class.
    static LRESULT CALLBACK MessageRouter(HWND, UINT, WPARAM, LPARAM);
};

And this is how you would would bind a member function to the this pointer and pass it to Win32::Initialize():

#include <functional>

// ...

void Engine::Initialize()
{
    using namespace std::placeholders;

    m_win32 = new Win32;
    m_win32->Initialize(std::bind(&Engine::WindowProc, this, _1, _2, _3 _4);
//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

Upvotes: 1

Related Questions