Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Manually loading OpenGL functions on linux
#include "opengl-api.h"
#include <dlfcn.h>
#include <stdio.h>
/* Here we define pointers to each of the opengl functions we use by defining a
* function-like macro "GL_FUNC" and applying it to each "GL_FUNC" macro
* contained by "GL_FUNC_LIST". This xmacro is defined in our header. */
#define GL_FUNC(returnType, funcName, ...) funcName##Type * funcName;
#undef GL_FUNC
/* Call this function once from whatever function initializes your opengl
* functions. */
int openglApiInit()
void * libGL = dlopen("", RTLD_LAZY);
if (!libGL)
printf("ERROR: couldn't be loaded\n");
return 0;
/* Here we load each opengl function by again defining a macro GL_FUNC
* and applying it to each GL_FUNC macro contained by GL_FUNC_LIST. */
#define GL_FUNC(returnType, funcName, ...) \
funcName = (funcName##Type *) dlsym(libGL, #funcName); \
if (!funcName) \
{ \
printf("Function " #funcName "couldn't be loaded from\n");\
return 0; \
#undef GL_FUNC
return 1;
* opengl-api.h: gets function pointers to gpu driver's opengl api
* To learn the reasons for loading opengl functions yourself, read
* <>
* Nice introduction to xmacros (heavily used here)
* <>
#ifndef OPENGL_API_H
#define OPENGL_API_H
#include <GL/gl.h>
* GL_FUNC_LIST is a macro that whenever used will produce a list of
* function-like macro "GL_FUNC" that can be defined, undefined, and redefined
* to do different things with the provided arguments.
* For example, GL_FUNC is defined below to create both typedefs for these
* opengl functions and declare them as extern. And in opengl-api.c, GL_FUNC is
* repeatedly defined, undefined, and redefined to create code that will define
* pointers to each of these functions as well as load them dynamically using
* This kind of macro is often called an xmacro, here's a nice explanation
* often them <>
#define GL_FUNC_LIST \
/* params: returnType, funcName, args... */ \
GL_FUNC(GLuint, glCreateShader, GLenum type) \
GL_FUNC(void, glShaderSource, GLuint shader, GLsizei count, const GLchar **string, const GLint *length) \
GL_FUNC(void, glCompileShader, GLuint shader) \
GL_FUNC(void, glGetShaderiv, GLuint shader, GLenum pname, GLint *params) \
GL_FUNC(void, glGetShaderInfoLog, GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) \
GL_FUNC(GLuint, glCreateProgram) \
GL_FUNC(void, glAttachShader, GLuint program, GLuint shader) \
GL_FUNC(void, glLinkProgram, GLuint program) \
GL_FUNC(void, glGetProgramiv, GLuint program, GLenum pname, GLint *params) \
GL_FUNC(void, glGetProgramInfoLog, GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) \
GL_FUNC(void, glDeleteShader, GLuint shader) \
GL_FUNC(void, glGenBuffers, GLsizei n, GLuint * buffers) \
GL_FUNC(void, glGenVertexArrays, GLsizei n, GLuint *arrays) \
GL_FUNC(void, glBindVertexArray, GLuint array) \
GL_FUNC(void, glBindBuffer, GLenum target, GLuint buffer) \
GL_FUNC(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) \
GL_FUNC(void, glVertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) \
GL_FUNC(void, glEnableVertexAttribArray, GLuint index) \
GL_FUNC(void, glUseProgram, GLuint program) \
GL_FUNC(void, glDeleteVertexArrays, GLsizei n, const GLuint *arrays) \
GL_FUNC(void, glDeleteBuffers, GLsizei n, const GLuint * buffers) \
GL_FUNC(void, glDeleteProgram, GLuint program)
#define GL_FUNC(returnType, funcName, ...) \
/* Create a typedef for the opengl function so the function pointers are shorter to type. */ \
typedef returnType funcName##Type(__VA_ARGS__); \
/* Declare function pointer as extern so files that include this header can reference it. */ \
extern funcName##Type * funcName;
/* So, because we've just defined GL_FUNC, when we next use the GL_FUNC_LIST
* macro, our GL_FUNC macro will run for each GL_FUNC in GL_FUNC_LIST. */
#undef GL_FUNC
int openglApiInit();
#endif // OPENGL_API_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment