GLFWPP or (GLFW C++ Wrapper) is a thin, modern C++17 layer on top of GLFW. It supports GLFW versions from 3.2 up to the current 3.3.6. From the official GLFW website:
GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan development on the desktop. It provides a simple API for creating windows, contexts and surfaces, receiving input and events. GLFW is written in C and supports Windows, macOS, X11 and Wayland. GLFW is licensed under the zlib/libpng license.
I like C++ and OOP, so when I find a C library, I immediately look for a wrapper which offers RAII objects instead of free create and destroy functions, identifiers wrapped in namespaces, methods instead of free functions, scoped enums instead of macros and exceptions instead of error codes. In case of GLFW I didn't really find such a library, so I made one myself.
⏱️ Quick Start
To use, just clone the repo recursively:
git clone https://github.com/janekb04/glfwpp --recurse-submodulesRemember to install the necessary GLFW dependencies, if you're on Linux. Make sure to disable building the examples by setting the option GLFWPP_BUILD_EXAMPLES to OFF using set(GLFWPP_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) in your CMakeLists.txt, if you don't want them built, as they are built by default. If you don't disable them, you will also have to install the Vulkan SDK.
You can then link against the target GLFWPP using CMake:
add_executable(myExecutable mySource1.cpp mySource2.cpp mySource3.cpp)
set(GLFWPP_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) # disable building GLFWPP examples
add_subdirectory("path/to/glfwpp")
target_link_libraries(myExecutable PRIVATE GLFWPP)Now, you just have to include glfwpp.h and you're ready to go:
#include <glfwpp/glfwpp.h>
int main()
{
auto GLFW = glfw::init();
glfw::Window window{ 640, 480, "Hello GLFWPP"};
while (!window.shouldClose())
glfw::pollEvents();
}You can also consult cmake.yml to see the complete installation and building process of GLFWPP, its dependencies and the examples on Ubuntu, macOS and Windows. Examples may be found in the /examples directory. Alternatively, just copy-paste the headers and include glfwpp.h (not recommended).
Note: To use functionality from glfw3native.h, native.h has to be included separately.
📌 Main Features
- Error handling using exceptions (defined in
error.h). - Strongly typed scoped enums for all GLFW constants that catch all
GLFW_INVALID_ENUMerrors at compile time. - Everything wrapped in namespace
glfwto avoid name clashing - RAII wrappers for windows (
glfw::Window), cursors (glfw::Cursor), key codes (glfw::KeyCode), monitors (glfw::Monitor), joysticks (glfw::Joystick) and the entire library (glfw::GlfwLibrary) for automatic resource management. glfw::Eventclass to allow to specify any invocable (function, method, lambda, functor, etc.) as a callback. Note: it usesstd::functionwhich is infamous for its poor performance. However, events occur relatively rarely (probably generally no more than a dozen a frame) and as such I wouldn't expect this to be a performance issue. At the same timestd::functionhas much greater flexibility than raw function pointers.- Hints passed through structures (
glfw::InitHintsandglfw::WindowHints) instead of through functions with an enum constant. - Mostly very thin wrapping matching nearly exactly the original GLFW naming which makes it both easier to port and allows to use the official GLFW documentation.
- Performance overhead should be low, due to the thin nature of the wrapper. Note: The
glfw::Eventas mentioned above could have a little performance overhead, but it shouldn't be an issue. Another factor is the use of exceptions for error handling. However, most exception implementations have performance penalties only in the exceptional path, which, by definition, happens rarely. - Now also compatible with Vulkan-Hpp.
- Now also compatible with Emscripten.
🎓 Example
Here is a quick comparison of GLFW and GLFWPP. The following code creates a OpenGL 4.6 context and clears the screen.
| GLFW | GLFWPP |
|---|---|
#include <GLFW/glfw3.h> int main() { if (!glfwInit()) return -1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", nullptr, nullptr); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); while (!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); } |
#include <glfwpp/glfwpp.h> int main() { auto GLFW = glfw::init(); |
📂 File structure
The functionality is split between files, as follows:
-
error.h- things related to error handling (exception types etc.). All GLFW errors are detected by the library and thrown as exceptions. The exception type matches the respective GLFW error code. -
glfwpp.h- main header with, includes all other headers. Contains:- The
initfunction. Initialization hints are passed withglfw::InitHints. The RAII wrapperglfw::GlfwLibrarytakes care of callingglfwTerminate(). - Time input.
- Clipboard input and output.
- Vulkan specific functionality. Compatible with both
vulkan.hand Vulkan-Hpp.
- The
-
event.h-glfw::Eventclass used for specifying all user callbacks as well as event management functions. -
joystick.h-glfw::Joystickclass and functionality related to joystick input -
monitor.h-glfw::Monitorand other functionality related to monitor management. -
window.h-glfw::Windowclass,glfw::Cursorclass,glfw::KeyCodeclass and other functionality related to managing windows, window contexts and window input (clipboard and time IO inglfwpp.h). Window hints are specified usingglfw::WindowHints. -
native.h- functions for native access wrapping aroundglfw3native.h. -
version.h- function for querying the GLFW runtime and compile time version and version string.
🔗 Interoperability
GLFWPP code and GLFW can be mixed with no issues as long as you mind these rules:
- If GLFW is initialized with
glfw::GlfwLibrary, you must not callglfwTerminateyourself and depend on it being called by the destructor ofglfw::GlfwLibrary. You may callglfwInitthough, but it won't have any effect. Also you should not useglfwSetErrorCallback,glfwSetMonitorCallbacknorglfwSetJoystickCallbackand instead use the appropriateglfw::XXXXevents to register your handlers. - If GLFW is initialized with
glfwInit, you can initialize it again withglfw::GlfwLibrary. All the created GLFW objects will remain in a valid and all state will be preserved except that the handlers error callback, monitor callback and joystick callback handlers will be intercepted by GLFWPP and to register your own handlers you will have to use the appropriateglfw::XXXXevent. - Where applicable,
glfw::objects provide conversion operation to and from the underlyingGLFWxxxx*handles. However it must be noted that the conversion to the underlying handles retains the ownership of those handles. As such, for example, you must notglfwDestroythem. At the same time the constructors from handles take the ownership of the given handle and as such in this case you also must notglfwDestroythem yourself.

