Функция обратного вызова в 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