我正在使用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);
};
也许这只是一个更普遍的回调问题,但我在互联网上找到的唯一一件事是围绕回调创建一些包装类。但它看起来不应该这么难。 提前致谢。
答案 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