简体   繁体   English

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

[英]Callback function in freeglut from object

I'm using MSVC++ and freeglut in order to use openGL. 我正在使用MSVC ++和freeglut来使用openGL。 Now, I have a class called Camera , which is pretty simple, but it also holds the function for the reshaping of my window. 现在,我有一个名为Camera的类,它非常简单,但它也保存了重塑窗口的功能。

My question is: how can I set glutReshapeFunc(void (*callback)(int,int)) to my function in my camera? 我的问题是:如何在我的相机中将glutReshapeFunc(void (*callback)(int,int))为我的函数?

I have the following code, which won't work, because of a compiler error: 我有以下代码,由于编译器错误,它将无法工作:

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

and my Camera class looks like this in Camera.h : 我的Camera类在Camera.h中看起来像这样:

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

Maybe this is just a more general callback question, but the only thing I found on the internet was creating some wrapper class around the callback. 也许这只是一个更普遍的回调问题,但我在互联网上找到的唯一一件事就是围绕回调创建一些包装类。 But it doesn't look like this should be so hard. 但它看起来不应该这么难。 Thanks in advance. 提前致谢。

There's no clean way to do this. 没有干净的方法来做到这一点。 C does not know about objects, so pointers-to-members don't work. C不知道对象,因此指向成员的指针不起作用。 C does not do templates, so functors don't work. C不做模板,所以仿函数不起作用。 The API does not even allow you to pass an arbitrary void *userData to your callback, so you can't pass the object around in that way either. API甚至不允许您将任意void *userData传递给回调,因此您也无法以这种方式传递对象。

So, indeed, you'll have to create a wrapper function that is not a member function, and you'll have to give it access to the Camera object instance somehow, through a static and/or global variable. 所以,实际上,你必须创建一个不是成员函数的包装器函数,并且你必须通过静态和/或全局变量以某种方式让它访问Camera对象实例。

If there can be multiple objects listening for this event, you could create a singleton class that allows you to register arbitrary listeners. 如果可以有多个对象侦听此事件,则可以创建一个允许您注册任意侦听器的单例类。

You can't connect it directly. 您无法直接连接它。 ReshapeCamera is a member function, it needs a camera instance in order to run. ReshapeCamera是一个成员函数,它需要一个相机实例才能运行。 The glut callback is a C function, which don't have an instance of camera to call your method. 过剩回调是一个C函数,它没有相机实例来调用你的方法。 You need to create a function that call the camera reshape method. 您需要创建一个调用相机重塑方法的函数。

It has nothing to do with a "C vs C++" thing. 它与“C vs C ++”无关。 You just need to understand what a member function call entails and basically what it compiles down to. 您只需要了解成员函数调用的含义以及它编写的内容。

myObject.memberFunction(); // This is what the programmer sees.
memberFunction(&myObject); // This is what the compiler sees.

A member function is a fancy description of a function that simply takes the object as a first parameter. 成员函数是函数的精美描述,它简单地将对象作为第一个参数。 It's just invisible in the actual parameter list. 它在实际参数列表中是不可见的。

void MyClass::memberFunction() // This is the declaration the programmer sees.
void memberFunction(MyClass* this) // This is what the compiler sees.

From there, C++ adds special semantics to make it easy to work in an object-oriented fashion. 从那里,C ++添加了特殊的语义,使其易于以面向对象的方式工作。 So, even though your object has a member function of the format void(int, int), it actually has the format void(Camera*, int, int), and that does not match the desired format! 因此,即使您的对象具有格式为void(int,int)的成员函数,它实际上也具有void(Camera *,int,int)格式,并且与所需格式不匹配! This is why static function members can be used for such function pointers. 这就是静态函数成员用于此类函数指针的原因。 Ever notice that static member functions cannot access the members of "this"? 有没有注意到静态成员函数无法访问“this”的成员? That is because static member functions do not pass an instance of the object representing "this". 这是因为静态成员函数传递表示“this”的对象的实例。

In effect, you could emulate much of object-oriented programming in plain C. If you make a set of functions that take a struct pointer as the first parameter, you gain many of the same advantages! 实际上,您可以在简单C中模拟大量面向对象的编程。如果您创建一组以结构指针作为第一个参数的函数,您将获得许多相同的优势!

The following demonstrates how to register ac callback function from c++ Its generally useful, not specific to glut. 下面演示了如何从c ++注册ac回调函数它通常很有用,不是特定于过剩。

Here is your client c++ program 这是您的客户端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;

} }

Here is the Camera.cpp 这是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);
}

and its header Camera.h 及其标题Camera.h

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

Notice the use of a c++ global class pointer ptr_global_instance 请注意使用c ++全局类指针ptr_global_instance

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM