2015-02-02 4 views
0

Я хотел бы использовать функцию-член в качестве функции обратного вызова (с использованием this function):Используйте функцию-член в качестве обратного вызова

glfwSetCursorPosCallback(window, (GLFWcursorposfun)(MyClass::mouseButtonChanged)); 

Я знаю, что это не возможно, так как мне нужен экземпляр MyClass для вызова метода mouseButtonChanged ,

Но что мне делать?

+0

То, что у вас нет механизма для указателя данных пользователя в этой функции, несколько удары. Может понадобиться статическая карта, доступная для обратного вызова, содержащего отображение вашего объекта GLWindow *. Было ли требование * * вызываемым * (что-то, что поддерживает функцию 'operator()'), я бы предложил решение 'std :: bind', но я не думаю, что оно будет работать в вашем случае. – WhozCraig

+0

Спасибо, но у меня нет поддержки C++ 11. –

+0

Вам не нужна поддержка C++ 11, если вы не используете 'std :: bind', и независимо от того, была ли вы или не поддерживала Ave C++ 11, это все равно не сработает для вас, поскольку Я упомянул выше. – WhozCraig

ответ

3

Вы можете использовать glfwSetWindowUserPointer, чтобы прикрепить класс C++, управляющий этим окном. После этого вы можете написать статическую функцию переадресации, чтобы в функции члена

От http://www.glfw.org/faq.html#how-do-i-use-c-methods-as-callbacks

2.16 «WindowManager» - Как я использую методы C++ как обратные вызовы?

Вы не можете использовать обычные методы как обратные вызовы, так как GLFW является библиотекой C и не знает об объектах и ​​указателях. Если вы хотите, чтобы получали обратные вызовы для объекта C++, используйте статические методы или обычные функции как обратные вызовы, сохраните указатель на объект, который вы хотите присвоить , вызовите в качестве указателя пользователя для окна и используйте его для вызова методов на вашего объекта ,

1

Вам необходимо пройти в функции указатель этого типа:

void (*)(GLFWindow*, double, double) 

К сожалению, это не выглядит, как они дают вам место для любого вида контекста аргумента. Таким образом, один подход является глобальным обратного вызова подход:

struct MyCallback { 
    static MyClass* obj; 

    static void callback(GLFWindow* window, double a, double b) { 
     obj->mouseButtonChanged(window, double a, double b); 
    } 
}; 

Используется как:

MyCallback::obj = &myObj; 
glfwSetCursorPosCallback(window, &MyCallback::callback); 

Это работает, потому что callback в настоящее время не требует экземпляра. К сожалению, теперь у нас есть глобальный MyClass*. Однако мы застряли в этом. Мы не можем использовать выражение std::bind() или лямбда здесь, потому что что-либо с захватом не будет конвертируемым в указатель функции.

[обновление] Так как вы можете добавить void* на window, вы также можете сделать это:

glfwSetWindowUserPointer(window, &myObj); 
glfwSetCursorPosCallback(window, +[](GLFWindow* win, double a, double b){ 
    static_cast<MyClass*>(glfwGetWindowUserPointer(win))->mouseButtonChanged(win, a, b); 
}); 

Где operator+ на лямбда, без захвата (например, один в этом случае) преобразует его в необработанный указатель функции.

+0

У меня проблема с этой строкой 'MyCallback :: obj = &myObj;', так как я создаю свой экземпляр в main.cpp (который включает MyClass.h); поэтому я не знаю, как получить доступ к нему в MyClass.cpp. –

+1

@arthur.sw Если вы добавляете обратный вызов из 'MyClass', тогда вам просто нужно' MyCallback :: obj = this; ' – Barry