来自对象的freeglut中的回调函数

时间:2011-02-15 19:02:59

标签: c++ opengl callback freeglut

我正在使用MSVC ++和freeglut来使用openGL。现在,我有一个名为Camera的类,它很简单,但它也保存了重塑窗口的功能。

我的问题是:如何在相机中将glutReshapeFunc(void (*callback)(int,int))设置为我的功能?

我有以下代码,由于编译器错误而无效:

int main(int argc, char **argv)
{
    Camera *camera = new Camera();
    glutReshapeFunc(camera->ReshapeCamera);
}

我的Camera类在 Camera.h 中显示如下:

class Camera
{
public:
    Camera(void);
    ~Camera(void);
    void ReshapeCamera(int width, int height);
};

也许这只是一个更普遍的回调问题,但我在互联网上找到的唯一一件事是围绕回调创建一些包装类。但它看起来不应该这么难。 提前致谢。

4 个答案:

答案 0 :(得分:10)

没有干净的方法可以做到这一点。 C不知道对象,因此指向成员的指针不起作用。 C不做模板,所以仿函数不起作用。 API甚至不允许您将任意void *userData传递给回调,因此您也无法以这种方式传递对象。

所以,实际上,您必须创建一个不是成员函数的包装函数,并且您必须通过静态和/或全局方式以某种方式为其提供对Camera对象实例的访问权限变量

如果可以有多个对象侦听此事件,您可以创建一个允许您注册任意侦听器的单例类。

答案 1 :(得分:2)

您无法直接连接。 ReshapeCamera是一个成员函数,它需要一个相机实例才能运行。过剩回调是一个C函数,它没有相机实例来调用你的方法。您需要创建一个调用相机重塑方法的函数。

答案 2 :(得分:1)

它与“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)格式,并且与所需格式不匹配!这就是静态函数成员可以用于此类函数指针的原因。有没有注意到静态成员函数无法访问“this”的成员?这是因为静态成员函数传递表示“this”的对象的实例。

实际上,您可以在简单C中模拟大部分面向对象的编程。如果您创建一组以结构指针作为第一个参数的函数,您将获得许多相同的优势!

答案 3 :(得分:0)

以下演示了如何从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;

}

这是Camera.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);
}

及其标题Camera.h

class Camera {
public:
    void ReshapeCamera_cb(int width, int height);
    void setup_callback();
};

请注意使用c ++全局类指针ptr_global_instance