1
votes

I'm trying to compile my first GL simple program with g++ on Linux using:

-lxcb-dri2 -lxcb-lm -ldl -lXrender -ldrm -lXdamage -lX11-xcb -lxcb-glx -dri3 -l-L/usr/local/lib -lrt -lXrandr -lXinerama -lXi -lXcursor -lGL -lm xcb-present -lglfw -lxcb-sync -lxshmfence -lXxf86vm -lXfixes -lXext -lX11 -lpthread -lxcb -lXau -lXdmcp -lGLEW

and I've got this error:

graphics/window.cpp: In member function 'bool je::graphics::Window::init()':
graphics/window.cpp:55:32: error: 'key_callback' was not declared in this scope glfwSetKeyCallback(m_Window, key_callback);

My code is in three files.

main.cpp:

#include "graphics/window.h"

int main()
{
    using namespace je;
    using namespace graphics;

    Window window("just engine", 800, 600);
    glClearColor(0.2f, 0.3f, 0.8f, 1.0f);

    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    while (!window.closed())
    {
        window.clear();
        if (window.isKeyPressed(GLFW_KEY_A))
        {
            std::cout << "PRESSED!" << std::endl;
        }

        glDrawArrays(GL_ARRAY_BUFFER, 0, 6);
        window.update();
    }
    return 0;
}

window.h:

#pragma once
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

namespace je{ namespace graphics{

#define MAX_KEYS    1024
#define MAX_BUTTONS     32

    class Window
    {
    private:

        const char *m_Title;
        int m_Width, m_Height;
        GLFWwindow *m_Window;
        bool m_Closed;
                static bool m_Keys[MAX_KEYS];
                static bool m_MouseButtons[MAX_BUTTONS];
                static double mx, my;
    public:
        Window(const char *name, int width, int height);
        ~Window();
                void clear() const;
        void update();
                bool closed() const;

        inline int getWidth() const {return m_Width; }
        int getHeight() const {return m_Height; }

        static bool isKeyPressed(unsigned int keycode);
        //friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
    private:
        bool init();
        friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
    };
}}

window.cpp:

#include "window.h"
#include <GLFW/glfw3.h>

namespace je{ namespace graphics {


    bool Window::m_Keys[MAX_KEYS];
    bool Window::m_MouseButtons[MAX_BUTTONS];
    double Window::mx;
    double Window::my;
    void window_resize(GLFWwindow *window, int width, int height);
    Window::Window(const char *title, int width, int height)
    {
        m_Title = title;
        m_Width = width;
        m_Height = height;
        if (!init())
            glfwTerminate();


        for (int i = 0; i < MAX_KEYS; i++)
        {
            m_Keys[i] = false;
        }
        for (int i = 0; i < MAX_BUTTONS; i++)
        {
            m_MouseButtons[i] = false;
        }
    }

    Window::~Window()
    {
        glfwTerminate();
    }

    bool Window::init()
    {

            if(!glfwInit())
            {
                std::cout << "Failed to initialize GLFW" << std::endl;
            return false;
        }
        m_Window = glfwCreateWindow(m_Width, m_Height, m_Title, NULL, NULL);
        if (!m_Window)
        {
            glfwTerminate();
            std::cout << "Creating window failed." << std::endl;
            return false;
        }

        glfwMakeContextCurrent(m_Window);
        glfwSetWindowUserPointer(m_Window, this);
        glfwSetWindowSizeCallback(m_Window, window_resize);
        glfwSetKeyCallback(m_Window, key_callback);

        if (glewInit() != GLEW_OK)
        {
            std::cout << "Could not initialize GLEW!" << std::endl;
            return false;
        }

                std::cout << "OpenGL " << glGetString(GL_VERSION) << std::endl;

        return true;
    }

        bool Window::isKeyPressed(unsigned int keycode)
    {
        if (keycode >= MAX_KEYS)
            return false;
        return m_Keys[keycode];
    }


    void Window::clear() const
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }

    void Window::update()
    {
        glfwPollEvents();
        glfwGetFramebufferSize(m_Window, &m_Width, &m_Height);
        glfwSwapBuffers(m_Window);
    }

        bool Window::closed() const
        {
                return glfwWindowShouldClose(m_Window) == 1;
        }

    void window_resize(GLFWwindow *window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }

        void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
    {
        Window* win = (Window*) glfwGetWindowUserPointer(window);
        win->m_Keys[key] = action != GLFW_RELEASE;
    }
} }

I'm really beginner and I'm lost in it... Could You help me find a way? Thank You.

1
You key_callback(...) is an member function, you can't use it as an argument. You should either create an wrapper or define it as static or simply define it outside the class.leyanpan
please consistently indent the code. Do not mix tabs and spaces when indenting. place 2 or 3 (be consistent) blank lines between functions for readability.user3629249
Looks like you are programming in C++ and not C. The C language does not have classes, constructors or destructors. I recommend you adjust the tags.Thomas Matthews

1 Answers

2
votes

To use the C++ member function void key_callback(), as a parameter to the C-implemented library function glfwSetKeyCallback(), you should declare it as static, but outside of the class declaration first. So try something like this for your window.h.

class Window;
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);

class Window {
    private:
        // fields here

    public:
        // other member functions here

    private:
        friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
};

And then in window.cpp:

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    Window* win = (Window*) glfwGetWindowUserPointer(window);
    win->m_Keys[key] = action != GLFW_RELEASE;
}

I haven't written in this glfw library, so my answer might not be sufficient for your purposes. Have a look at these questions: Pointing to a function that is a class member , Is it possible to declare a friend function as static?