8

openGL を使用するために、MSVC++ と freeglut を使用しています。という名前のクラスがあり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

4 に答える 4

10

これを行うためのクリーンな方法はありません。Cはオブジェクトを認識しないため、メンバーへのポインターは機能しません。Cはテンプレートを実行しないため、ファンクターは機能しません。APIではvoid *userData、コールバックに任意の値を渡すことさえできないため、その方法でオブジェクトを渡すこともできません。

したがって、実際には、メンバー関数ではないラッパー関数を作成する必要がありCamera、静的変数やグローバル変数を介して、何らかの方法でオブジェクトインスタンスへのアクセスを許可する必要があります。

このイベントをリッスンする複数のオブジェクトが存在する可能性がある場合は、任意のリスナーを登録できるシングルトンクラスを作成できます。

于 2011-02-15T19:09:53.273 に答える
2

直接接続することはできません。ReshapeCameraはメンバー関数であり、実行するにはカメラインスタンスが必要です。glutコールバックはC関数であり、メソッドを呼び出すためのカメラのインスタンスがありません。カメラの形状変更メソッドを呼び出す関数を作成する必要があります。

于 2011-02-15T19:08:39.127 に答える
2

「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 でオブジェクト指向プログラミングの多くをエミュレートできます。構造体ポインターを最初のパラメーターとして受け取る一連の関数を作成すると、同じ利点の多くが得られます。

于 2011-02-15T21:22:35.080 に答える
0

以下は、c++ から ac コールバック関数を登録する方法を示しています。これは一般的に有用ですが、glut に固有のものではありません。

クライアントの 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 の使用に注意してください。

于 2013-08-04T20:00:40.647 に答える