3

我一直致力于创建一个 OpenGL 函数加载库,它可以帮助我在需要时调用 OpenGL 函数。

我有一个getProcAddress使用 glX 的函数。

void* getProcAddress(const char *name)
{
    auto pr = reinterpret_cast<void*>(glXGetProcAddress(
            reinterpret_cast<const unsigned char*>(name)));

    return pr;
}

这将返回 OpenGL 函数的地址。如果我不使用reinterpret_casts,我会收到奇怪的编译器错误,这就是它们存在的原因。

然后我在头文件中定义一个 gl* 函数原型:

typedef void _GLACTIVETEXTURE(GLenum texture);

whereGLenum在另一个头文件中定义为枚举。然后我在一个类中声明函数指针:

_GLACTIVETEXTURE glActiveTexture;

然后在一个名为initI 的函数中:

void GLFunctions::init()
{
    glActiveTexture = (_GLACTIVETEXTURE)getProcAddress("glActiveTexture");
}

getProcAddress函数可以自行编译,但上面的代码行不会编译。GCC 抛出此编译器错误:

error: invalid cast to function type ‘_GLACTIVETEXTURE {aka void(GLenum)}’

而且我不知道如何处理这种编译器错误。这是没有意义的,因为这是一个函数指针,而不是函数本身,除非我使用(). 我不太确定这里的问题是什么;无论是我这边还是海湾合作委员会。目前还不清楚。我试过摆弄指针和空位,但一切都是徒劳的,并且出现了相同的错误消息。有谁知道这里发生了什么以及如何正确调用 OpenGL 函数?

4

2 回答 2

5

@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 *可以保存指向函数的指针。但是,将指向函数的指针转换为指向另一种数据类型(除了void *)的指针的结果仍未定义。void *请注意,如果尝试从指针到函数指针的转换,则需要符合 ISO C 标准的编译器生成警告,如下所示:

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意识到了这一点,并已明确编写,以便它返回一个函数指针。但是因为函数指针与常规指针不同,所以不能将函数指针转换为常规指针。相反,您必须转换为目标函数指针类型,或者在赋值中转换函数指针变量左值(与 dlsym 一样)以匹配 glXGetProcAddress 的右值。

于 2016-07-30T15:09:33.097 回答
3

typedef错了。您正在创建函数类型的别名,而不是函数指针。这是正确完成的方式:

typedef void (*_GLACTIVETEXTURE)(GLenum texture);
于 2016-07-30T13:00:06.620 回答