我一直致力于创建一个OpenGL函数加载库,它可以帮助我在需要时调用OpenGL函数。
我有一个使用glX的getProcAddress
函数。
void* getProcAddress(const char *name)
{
auto pr = reinterpret_cast<void*>(glXGetProcAddress(
reinterpret_cast<const unsigned char*>(name)));
return pr;
}
返回OpenGL函数的地址。如果我不使用reinterpret_cast
s,那么我会遇到奇怪的编译错误,这就是为什么他们会在那里。
然后我在头文件中定义了一个gl *函数原型:
typedef void _GLACTIVETEXTURE(GLenum texture);
其中GLenum
在另一个头文件中定义为枚举。然后我在类中声明函数指针:
_GLACTIVETEXTURE glActiveTexture;
然后在名为init
的函数中执行:
void GLFunctions::init()
{
glActiveTexture = (_GLACTIVETEXTURE)getProcAddress("glActiveTexture");
}
getProcAddress
函数自行编译很好,但上面的代码行不会编译。 GCC抛出此编译器错误:
error: invalid cast to function type ‘_GLACTIVETEXTURE {aka void(GLenum)}’
而且我不知道如何处理这种编译器错误。它没有任何意义,因为这是一个函数指针,而不是函数本身,除非我使用()
。我不确定这里的问题是什么;无论是来自我方还是海湾合作委员会。目前尚不清楚。我试图摆弄指针和空洞,但都是徒劳的,同样的错误信息出现了。有谁知道这里发生了什么,以及如何正确调用OpenGL函数?
答案 0 :(得分:4)
@nshct已经解释了为什么编译器会抱怨你的代码。这个答案没有解决的问题是,为什么你的reinterpret_cast
首先是必要的。其原因在于,函数指针与常规指针不同,sizeof(void*) != sizeof(void(*)(void))
完全可能,即函数指针可能具有与常规指针完全不同的值范围和对齐规则。 dlsym
的手册页详细说明了这一点:
http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
原理
ISO C标准不要求指向函数的指针 来回转向指向数据的指针。的确,ISO C标准 不要求
void *
类型的对象可以保存指针 一个功能。但是,支持XSI扩展的实现可以 要求void *
类型的对象可以保存指向a的指针 功能。将指针转换为函数的结果 指向另一种数据类型(void *
除外)的指针仍未定义, 然而。请注意,符合ISO C标准的编译器是 如果从void *
指针进行转换,则需要生成警告 尝试使用函数指针,如下所示:fptr = (int (*)(int))dlsym(handle, "my_function");
由于此处提到的问题,未来版本可能会添加新版本 函数返回函数指针,或者当前界面可能是 不推荐使用两个新函数:一个返回数据 指针和另一个返回函数指针。
因此,当使用dlsym
时,必须使用特殊的铸造方法,即一些左值铸造技巧。
void *handle;
int (*fptr)(int);
/* open the needed object */
handle = dlopen("/usr/home/me/libfoo.so", RTLD_LOCAL | RTLD_LAZY);
/* find the address of function and data objects */
*(void **)(&fptr) = dlsym(handle, "my_function");
glXGetProcAddress
的定义知道这一点,并且已经明确写入,以便返回一个函数指针。但是因为函数指针与常规指针不同,所以不能将函数指针强制转换为常规指针。相反,您必须转换为目标函数指针类型,或者在赋值中转换函数指针变量lvalue(与dlsym一样)以匹配glXGetProcAddress的rvalue。
答案 1 :(得分:3)
您的typedef
错了。您正在为函数类型创建别名,而不是函数指针。这是正确的做法:
typedef void (*_GLACTIVETEXTURE)(GLenum texture);