我目前正在编写一个openGL着色器类。我没有使用函数来设置每个统一类型,而是试图将统一函数(例如glUniform1f)作为参数传递。
我目前的尝试看起来像这样:
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);
但是,我经常遇到转换错误,如:
cannot convert argument 1 from 'void (__stdcall *)(GLint,GLfloat)' to 'void (__cdecl *)(GLint,GLfloat)'
是否可以按预期工作?
由于
注意:如果这很重要,我正在使用GLEW和glfw
答案 0 :(得分:3)
来自OpenGL加载库的函数指针(特别是那些返回直接从DLL加载的函数的函数)有时会使用与常规函数指针不同的调用约定进行注释。
此类函数指针不可互换。
有两种方法可以解决这个问题。您可以使用不同的OpenGL加载库,它处理使用标准调用约定的函数指针(实质上,隐藏它加载的实际指针)。例如,在my glLoadGen loader中,如果使用func_cpp
生成器样式,则所有函数都将是常规C ++函数。
否则,您必须更改在接口中声明函数指针的方式,以匹配加载程序的工作方式。例如,如果您正在使用GLEW,则必须执行以下操作:
void Shader::setUniform(void (GLAPIENTRY* fnc)(GLint, T1), const GLchar *name, const T1 value1)
答案 1 :(得分:1)
你也可以在functor的类型上模板化函数,免于处理函数指针语法,调用约定等。这个版本将接受所有可以用文档参数调用的东西(无论是函数,函数对象, lambda等)。它同时也是主要的优势和劣势。希望在下一版本的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);
}
我同意评论,这并没有太大变化,因为用户仍然键入函数名称和所有参数。 更多&#34;面向对象&#34;方法可能是为制服引入模板化的类,并根据参数类型对其进行专门化(没有多少)。