2011-02-15 74 views
8

我使用MSVC++和freeglut为了使用openGL。现在,我有一个名为Camera的类,它非常简单,但它也具有重塑我的窗口的功能。从对象的freeglut回调函数

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

我有下面的代码,这是行不通的,因为编译器错误的,:

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

和我的相机类看起来像这样Camera.h

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

也许这只是一个更普遍的回调问题,但我在互联网上发现的唯一的东西是围绕回调创建一些包装类。但看起来这不应该如此艰难。 在此先感谢。

回答

10

有没有干净的方式来做到这一点。 C不知道对象,所以指向成员的指针不起作用。 C不会做模板,所以仿函数不起作用。 API甚至不允许你传递一个任意的void *userData到你的回调函数中,所以你也不能以这种方式传递对象。

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

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

2

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

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中模拟大部分面向对象的编程。如果您创建了一组将函数作为第一个参数的结构指针,您将获得许多相同的优点!

+0

所以我现在在我的类中创建了一个静态函数,但它似乎无法从__thiscall转换为__decl。错误1错误C2664:'glutReshapeFunc':无法将参数1从'void(__thiscall Camera :: *)(int,int)'转换为'void(__cdecl *)(int,int)'`。添加一个明确的__cdecl会给出一个关于`Camera ::`-part的警告。 – Marnix 2011-02-16 10:43:22

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