record GLFunction[Names, Type] { ptr: Type; } [Names, Type] pointerDereference(fn:GLFunction[Names, Type]) = ptr; overloadable getGLProcAddress; overload getGLProcAddress() { return null(Void); } overload getGLProcAddress(name:CString, ...) { var ptr = wglGetProcAddress(name); if (null?(ptr)) return getGLProcAddress(...); else return ptr; } [Name, Type] initGLFunction(fn:GLFunction[Names,Type]) { fn.ptr <-- Type(getGLProcAddress(...Names)); } // ... gl functions ... var glDrawElements : GLFunction[ ("glDrawElements", "glDrawElementsEXT", "glDrawElementsARB"), CCodePointer[GLenum, GLsizei, GLenum, Pointer[GLvoid], Void] ]; // ... gl functions ... initAllGLFunctions() { // ... initGLFunction(gl function); ... initGLFunction(glDrawElements); // ... initGLFunction(gl function); ... } someGLFunction() { // ... glDrawElements^(GL_TRIANGLES, 100, GL_UNSIGNED_SHORT, vertices); }