2016-10-11 2 views
0

現在、私はOpenGLシェーダクラスを作成中です。代わりに各ユニフォーム型を設定する関数を浮かべる、私はパラメータとして一様関数(例えば、glUniform1f)を渡そうとしています。それはすることが可能であるglUniform関数をパラメータとして渡す(C++)

cannot convert argument 1 from 'void (__stdcall *)(GLint,GLfloat)' to 'void (__cdecl *)(GLint,GLfloat)' 

template <typename T1> 
void Shader::setUniform(void (* fnc)(GLint, T1), const GLchar *name, const T1 value1) 
{ 
    fnc(getUniformLocation(name), value1); 
} 

しかし、私は常に取得しています変換エラー

shader.setUniform<GLfloat>(*glUniform1f, "test", 5); 

と呼ばれるように:

私の現在の試みは、次のようになりますこれは意図したとおりに動作しますか?

おかげ

注:これは時々でアノテートされます

+0

私はopenGLに慣れていませんが、関数ポインタの代わりに 'std :: function'を使って関数を渡そうとしましたか? – Exagon

+0

まだ、ちょっとです。 –

+2

より良い質問は...なぜあなたはしたいですか?ここでのあなたの目標は、glUniform関数群のためのテンプレートラッパーを持っているようです。しかし、あなたのやり方では、ユーザは型( '' GLfloat')と関数ポインタの両方を渡す必要があります。型はすでに型を持っています。あなたがしようとしているようなことをする優れた方法がなければなりません。 –

答えて

3

関数ポインタ(DLLから直接ロード機能を返すものは特に)OpenGLの読み込みライブラリから重要である場合、私はGLEWを使用してGLFWています通常の関数ポインタからの異なる呼び出し規約。

このような関数ポインタは、ではなく、相互変換可能です。

これには2通りの方法があります。別のOpenGLロードライブラリを使うことができます.1つは標準の呼び出し規約を使う関数ポインタを扱うものです(実際にロードする実際のポインタは隠しています)。たとえば、my glLoadGen loaderでは、func_cppジェネレータースタイルを使用すると、すべての関数が通常のC++関数になります。

そうしないと、インターフェイスでの関数ポインタの宣言方法を変更して、ローダーの動作に合わせる必要があります。あなたがGLEWを使用している場合たとえば、あなたはこのような何かをしなければならないでしょう:

void Shader::setUniform(void (GLAPIENTRY* fnc)(GLint, T1), const GLchar *name, const T1 value1) 
1

あなたはなど、この規則を呼び出し、関数ポインタの構文を扱うから自分を温存、同様にファンクタの型の機能をテンプレート化できバージョンは、文書化された引数(関数、関数オブジェクト、ラムダなど)で呼び出すことができるすべてを受け入れます。それは同時に主要な強さと弱さです。コンセプトを介した型の制限は、次のバージョンのC++標準でうまく導入されるはずです。

template <typename F, typename T1> 
// requires: F callable with parameter types GLint, T1 
void Shader::setUniform(F fnc, const GLchar* name, const T1 value1) { 
    fnc(getUniformLocation(name), value1); 
} 

int main() { 
    ... 
    shader.setUniform(glUniform1f, "foo", 3.14f); 
} 

私は、ユーザーがまだ関数名とすべてのパラメータを入力しているので、これはあまり変更されていないという意見に同意します。 もっと「オブジェクト指向の」アプローチは、制服のためのテンプレート化されたクラスを導入し、引数タイプごとにそれを特殊化することです(多くはありません)。

関連する問題