Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually calling OpenGL functions

Tags:

c++

gcc

opengl

glx

I've been working on creating an OpenGL function loading library which will help me call OpenGL functions when I need them.

I have a getProcAddress function which uses glX.

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

    return pr;
}

This returns the address of an OpenGL function. I get weird compiler errors if I don't use reinterpret_casts so that's why they're there.

I then define a gl* function prototype in a header file:

typedef void _GLACTIVETEXTURE(GLenum texture);

Where GLenum is defined in another header file as an enum. I then declare the function pointer in a class:

_GLACTIVETEXTURE glActiveTexture;

And then in a function called init I do:

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

The getProcAddress function compiles by itself fine, but the above line of code won't compile. GCC throws this compiler error:

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

And I don't know how to deal with this kind of compiler error. It makes no sense because this is a function pointer, not a function itself unless I use (). I'm not really sure what the problem here is; whether it's from my side or GCC. It's not clear. I've tried fiddling around with the pointers and voids, but all in vain and the same error message comes up. Does anyone know what's going on here and how I can properly call OpenGL functions?

like image 546
Poriferous Avatar asked Mar 10 '26 06:03

Poriferous


1 Answers

@nshct already gave you an explanation why compilers complain about your code. What that answer didn't address is, why your reinterpret_cast was necessary in the first place. The reason for that is, that function pointers are something different than regular pointers and it's perfectly possible that sizeof(void*) != sizeof(void(*)(void)), i.e. function pointers may have an entirely different range of values and alignment rules than regular pointers. The man page for dlsym addresses this in detail:

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.

Because of that when using dlsym a special way of casting must be used, namely some lvalue casting trickery.

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");

The definition of glXGetProcAddress is aware of this and has explicitly been written so that it returns a function pointer. But because function pointers are different from regular pointers you must not cast a function pointer into a regular pointer. Instead you must cast either to the target function pointer type, or cast the function pointer variable lvalue in the assignment (as with dlsym) to match the rvalue of glXGetProcAddress.

like image 105
datenwolf Avatar answered Mar 11 '26 19:03

datenwolf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!