手动调用 OpenGL 函数
Manually calling OpenGL functions
我一直致力于创建一个 OpenGL 函数加载库,它将帮助我在需要时调用 OpenGL 函数。
我有一个使用 glX 的 getProcAddress
函数。
void* getProcAddress(const char *name)
{
auto pr = reinterpret_cast<void*>(glXGetProcAddress(
reinterpret_cast<const unsigned char*>(name)));
return pr;
}
此 returns OpenGL 函数的地址。如果我不使用 reinterpret_cast
s,我会得到奇怪的编译器错误,所以这就是它们存在的原因。
然后我在头文件中定义一个 gl* 函数原型:
typedef void _GLACTIVETEXTURE(GLenum texture);
其中GLenum
在另一个头文件中定义为枚举。然后我在 class:
中声明函数指针
_GLACTIVETEXTURE glActiveTexture;
然后在一个名为 init
的函数中我做:
void GLFunctions::init()
{
glActiveTexture = (_GLACTIVETEXTURE)getProcAddress("glActiveTexture");
}
getProcAddress
函数可以自行编译,但上面的代码行无法编译。 GCC 抛出此编译器错误:
error: invalid cast to function type ‘_GLACTIVETEXTURE {aka void(GLenum)}’
而且我不知道如何处理这种编译器错误。这没有意义,因为这是一个函数指针,而不是函数本身,除非我使用 ()
。我不太确定这里的问题是什么;无论是我这边还是 GCC。目前还不清楚。我试过摆弄指针和空隙,但都是徒劳的,并且出现了相同的错误消息。有谁知道这里发生了什么以及我如何正确调用 OpenGL 函数?
你的typedef
错了。您正在为函数 type 创建别名,而不是函数 pointer。这是正确的做法:
typedef void (*_GLACTIVETEXTURE)(GLenum texture);
@nshct 已经向您解释了为什么编译器会抱怨您的代码。该答案没有解决的是,为什么您的 reinterpret_cast
首先是必需的。这样做的原因是,函数指针与常规指针不同,并且完全有可能 sizeof(void*) != sizeof(void(*)(void))
,即函数指针可能具有与常规指针完全不同的值范围和对齐规则。 dlsym
的手册页详细解决了这个问题:
http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
Rationale
The ISO C standard does not require that pointers to functions can be
cast back and forth to pointers to data. Indeed, the ISO C standard
does not require that an object of type void *
can hold a pointer to
a function. Implementations supporting the XSI extension, however, do
require that an object of type void *
can hold a pointer to a
function. The result of converting a pointer to a function into a
pointer to another data type (except void *
) is still undefined,
however. Note that compilers conforming to the ISO C standard are
required to generate a warning if a conversion from a void *
pointer
to a function pointer is attempted as in:
fptr = (int (*)(int))dlsym(handle, "my_function");
Due to the problem noted here, a future version may either add a new
function to return function pointers, or the current interface may be
deprecated in favor of two new functions: one that returns data
pointers and the other that returns function pointers.
因此在使用 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
的定义意识到了这一点,并明确地写成 returns 一个函数指针。但是因为函数指针不同于常规指针,所以您不能将函数指针转换为常规指针。相反,您必须转换为目标函数指针类型,或者在赋值中转换函数指针变量左值(与 dlsym 一样)以匹配 glXGetProcAddress 的右值。
我一直致力于创建一个 OpenGL 函数加载库,它将帮助我在需要时调用 OpenGL 函数。
我有一个使用 glX 的 getProcAddress
函数。
void* getProcAddress(const char *name)
{
auto pr = reinterpret_cast<void*>(glXGetProcAddress(
reinterpret_cast<const unsigned char*>(name)));
return pr;
}
此 returns OpenGL 函数的地址。如果我不使用 reinterpret_cast
s,我会得到奇怪的编译器错误,所以这就是它们存在的原因。
然后我在头文件中定义一个 gl* 函数原型:
typedef void _GLACTIVETEXTURE(GLenum texture);
其中GLenum
在另一个头文件中定义为枚举。然后我在 class:
_GLACTIVETEXTURE glActiveTexture;
然后在一个名为 init
的函数中我做:
void GLFunctions::init()
{
glActiveTexture = (_GLACTIVETEXTURE)getProcAddress("glActiveTexture");
}
getProcAddress
函数可以自行编译,但上面的代码行无法编译。 GCC 抛出此编译器错误:
error: invalid cast to function type ‘_GLACTIVETEXTURE {aka void(GLenum)}’
而且我不知道如何处理这种编译器错误。这没有意义,因为这是一个函数指针,而不是函数本身,除非我使用 ()
。我不太确定这里的问题是什么;无论是我这边还是 GCC。目前还不清楚。我试过摆弄指针和空隙,但都是徒劳的,并且出现了相同的错误消息。有谁知道这里发生了什么以及我如何正确调用 OpenGL 函数?
你的typedef
错了。您正在为函数 type 创建别名,而不是函数 pointer。这是正确的做法:
typedef void (*_GLACTIVETEXTURE)(GLenum texture);
@nshct 已经向您解释了为什么编译器会抱怨您的代码。该答案没有解决的是,为什么您的 reinterpret_cast
首先是必需的。这样做的原因是,函数指针与常规指针不同,并且完全有可能 sizeof(void*) != sizeof(void(*)(void))
,即函数指针可能具有与常规指针完全不同的值范围和对齐规则。 dlsym
的手册页详细解决了这个问题:
http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
Rationale
The ISO C standard does not require that pointers to functions can be cast back and forth to pointers to data. Indeed, the ISO C standard does not require that an object of type
void *
can hold a pointer to a function. Implementations supporting the XSI extension, however, do require that an object of typevoid *
can hold a pointer to a function. The result of converting a pointer to a function into a pointer to another data type (exceptvoid *
) is still undefined, however. Note that compilers conforming to the ISO C standard are required to generate a warning if a conversion from avoid *
pointer to a function pointer is attempted as in:fptr = (int (*)(int))dlsym(handle, "my_function");
Due to the problem noted here, a future version may either add a new function to return function pointers, or the current interface may be deprecated in favor of two new functions: one that returns data pointers and the other that returns function pointers.
因此在使用 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
的定义意识到了这一点,并明确地写成 returns 一个函数指针。但是因为函数指针不同于常规指针,所以您不能将函数指针转换为常规指针。相反,您必须转换为目标函数指针类型,或者在赋值中转换函数指针变量左值(与 dlsym 一样)以匹配 glXGetProcAddress 的右值。