openGLUTのコールバック関数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kyz

openGLUTのコールバック関数について

#1

投稿記事 by kyz » 7年前

いつもお世話になっております。
openGLUTのコールバック関数である glutDisplayFunc(void (*callback))の引数にクラスのメンバ関数を指定したいのですが、どういう方法を取ればいいでしょうか?

コード:

class Room{

public:

	Room(){
init_OpenGL();
        }

	void display(){

        /* 内容省略 */

	}

	void init_OpenGL(){
		glutDisplayFunc(display);//ここでコールバック関数を登録したい
		glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
		glClearColor(1.0, 1.0, 1.0, 1.0);
		glEnable(GL_DEPTH_TEST);
	}

};
これをコンパイルしてみると、

error C3867: 'Room::display': 関数呼び出しには引数リストがありません。メンバーへのポインターを作成するために '&Room::display' を使用してください

このようなエラーが出て来ました。
また&Room::displayと書きなおしてみても、

error C2664: 'glutDisplayFunc' : 1 番目の引数を 'void (__thiscall Room::* )(void)' から 'void (__cdecl *)(void)' に変換できません。(新しい機能 ; ヘルプを参照)

と出て来てコンパイルできませんでした。

環境は、OS:windows 7(64bit) 開発環境:Visual Studio2012 for Desktop(C/C++) を使って開発しています。

アバター
usao
記事: 1598
登録日時: 7年前

Re: openGLUTのコールバック関数について

#2

投稿記事 by usao » 7年前

指定すべきコールバック関数は,普通の(クラスメンバではない)関数なので,
Room::display() では 求められている関数とは型が違うわけで,当然エラーとなります.

staticなメンバ関数であれば渡せるでしょうが,結局,Room型インスタンスを知ることはできないので
何かしらの妥協(別途インスタンスを知る方法を用意して,コールバック内から使う方法を用意する)をする必要があると思います.

仮に,プログラム内にRoom型インスタンスが一つしか存在しないことを保証できるのであれば,そこらへんのことも
わりと自然な形で解決できるように思います.

kyz

Re: openGLUTのコールバック関数について

#3

投稿記事 by kyz » 7年前

usao さんが書きました:指定すべきコールバック関数は,普通の(クラスメンバではない)関数なので,
Room::display() では 求められている関数とは型が違うわけで,当然エラーとなります.

staticなメンバ関数であれば渡せるでしょうが,結局,Room型インスタンスを知ることはできないので
何かしらの妥協(別途インスタンスを知る方法を用意して,コールバック内から使う方法を用意する)をする必要があると思います.

仮に,プログラム内にRoom型インスタンスが一つしか存在しないことを保証できるのであれば,そこらへんのことも
わりと自然な形で解決できるように思います.
分かりました。構造的に難しいという訳ですね。
これじゃ不便なので自らC++風にコールバック関数を定義してみたいと思います。
お早いご回答ありがとうございました。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: openGLUTのコールバック関数について

#4

投稿記事 by h2so5 » 7年前

Roomのポインタをグローバルに持っておくのも方法の一つだと思います。

コード:

namespace DisplayCallback {
namespace {
std::list<Room*> listeners;
}

void callback()
{
    for (std::vector<Room*>::iterator it = listeners.begin(); it != listeners.end(); ++it)
        it->display();
}

void addListener(Room *ptr)
{
    listeners.push_back(ptr);
}
}

// プログラム初期化時に呼ぶ
glutDisplayFunc(DisplayCallback::callback);

// コールバック登録
void Room::init_OpenGL()
{
    DisplayCallback::addListener(this);
}

閉鎖

“C言語何でも質問掲示板” へ戻る