Функция обратного вызова в freeglut из объекта
Я использую MSVC++ и freeglut для использования openGL. Теперь у меня есть класс под названием Camera
, что довольно просто, но также содержит функцию для изменения формы моего окна.
мой вопрос: как я могу установить glutReshapeFunc(void (*callback)(int,int))
к моей функции в моей камере?
у меня есть следующий код, который не работает, из-за ошибки компилятора:
int main(int argc, char **argv)
{
Camera *camera = new Camera();
glutReshapeFunc(camera->ReshapeCamera);
}
и мой класс камеры выглядит так в камера.h:
class Camera
{
public:
Camera(void);
~Camera(void);
void ReshapeCamera(int width, int height);
};
может быть, это это просто более общий вопрос обратного вызова, но единственное, что я нашел в интернете, это создание некоторого класса-оболочки вокруг обратного вызова. Но не похоже, что это должно быть так тяжело. Спасибо заранее.
4 ответов
нет чистого способа сделать это. C не знает об объектах, поэтому указатели на члены не работают. C не делает шаблонов, поэтому функторы не работают. API даже не позволяет передать произвольное void *userData
к вашему обратному вызову, поэтому вы не можете передать объект таким образом.
Итак, действительно, вам придется создать функцию-оболочку, которая не является функцией-членом, и вам придется предоставить ей доступ к Camera
экземпляр объекта каким-то образом, через статический и / или глобальная переменная.
Если для этого события может прослушиваться несколько объектов, можно создать одноэлементный класс, позволяющий регистрировать произвольные прослушиватели.
вы не можете подключить его напрямую. ReshapeCamera-это функция-член, ей нужен экземпляр камеры для запуска. Обратный вызов glut-это функция C, у которой нет экземпляра camera для вызова вашего метода. Необходимо создать функцию, вызывающую метод reshape камеры.
это не имеет ничего общего с" C vs C++". Вам просто нужно понять, что влечет за собой вызов функции-члена и в основном то, что он компилирует.
myObject.memberFunction(); // This is what the programmer sees.
memberFunction(&myObject); // This is what the compiler sees.
функция-член-это причудливое описание функции, которая просто принимает объект в качестве первого параметра. Он просто невидим в списке фактических параметров.
void MyClass::memberFunction() // This is the declaration the programmer sees.
void memberFunction(MyClass* this) // This is what the compiler sees.
оттуда C++ добавляет специальную семантику, чтобы упростить работу объектно-ориентированным способом. Поэтому, даже если ваш объект имеет функция-член формата void(int, int), на самом деле имеет формат void (Camera*, int, int), и это не соответствует желаемому формату! Вот почему статические члены функции can используется для таких указателей функций. Когда-нибудь замечали, что статические функции-члены не могут получить доступ к членам "этого"? Это потому, что статические функции-члены не передайте экземпляр объекта, представляющего "это".
по сути, вы можете эмулировать большую часть объектно-ориентированных программирование в простом C. Если вы сделаете набор функций, которые принимают указатель структуры в качестве первого параметра, вы получите много таких же преимуществ!
ниже показано, как зарегистрировать функцию обратного вызова c из C++ Его вообще полезно, не специфично для перенасыщения.
вот ваша клиентская программа c++
int main(int argc, char *argv[]) {
std::cout << "launching Camera ..." << std::endl;
Camera * camera = new Camera();
// ------ glut new window boilerplate ------- //
int WindowHandle = 0;
glutInit(&argc, argv);
WindowHandle = glutCreateWindow("hello there");
if(WindowHandle < 1) {
std::cerr << "ERROR: Could not create a new rendering window" << std::endl;
exit(EXIT_FAILURE);
}
// ------------------------------------------ //
camera->setup_callback();
glutMainLoop();
return 0;
}
вот камера.cpp
Camera * ptr_global_instance = NULL;
extern "C" void ReshapeCamera_callback(int width, int height) {
// c function call which calls your c++ class method
ptr_global_instance->ReshapeCamera_cb(width, height);
}
void Camera::ReshapeCamera_cb(int width, int height) {
std::cout << "width " << width << " height " << height << std::endl;
}
void Camera::setup_callback() {
// c++ method which registers c function callback
::ptr_global_instance = this;
::glutReshapeFunc(::ReshapeCamera_callback);
}
и его камера заголовка.h
class Camera {
public:
void ReshapeCamera_cb(int width, int height);
void setup_callback();
};
обратите внимание на использование указателя глобального класса c++ ptr_global_instance