freeglut 中对象的回调函数

发布于 2024-10-17 13:13:13 字数 600 浏览 1 评论 0原文

我使用 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);
};

也许这只是一个更一般的回调问题,但唯一的我在互联网上发现的事情是围绕回调创建一些包装类。但看起来这并不应该那么难。 提前致谢。

I'm using MSVC++ and freeglut in order to use openGL. Now, I have a class called Camera, which is pretty simple, but it also holds the function for the reshaping of my window.

My question is: how can I set glutReshapeFunc(void (*callback)(int,int)) to my function in my camera?

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:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦回旧景 2024-10-24 13:13:13

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

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

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

There's no clean way to do this. C does not know about objects, so pointers-to-members don't work. C does not do templates, so functors don't work. 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.

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.

If there can be multiple objects listening for this event, you could create a singleton class that allows you to register arbitrary listeners.

最丧也最甜 2024-10-24 13:13:13

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

You can't connect it directly. ReshapeCamera is a member function, it needs a camera instance in order to run. The glut callback is a C function, which don't have an instance of camera to call your method. You need to create a function that call the camera reshape method.

柒夜笙歌凉 2024-10-24 13:13:13

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

It has nothing to do with a "C vs C++" thing. 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. 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! 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"? That is because static member functions do not pass an instance of the object representing "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!

我做我的改变 2024-10-24 13:13:13

下面演示如何从c++注册ac回调函数
它通常有用,而不是专门针对过剩。

这是您的客户端 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 的使用

The following demonstrates how to register a c callback function from c++
Its generally useful, not specific to glut.

Here is your client c++ program

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 * 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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文