11#pragma once
22
33#include < cstddef>
4+ #include < cstring>
45#include < string>
56
67#ifndef __EMSCRIPTEN__
@@ -330,6 +331,38 @@ auto IsCurrentWgl() -> bool;
330331
331332// ---------------- Inline implementations -----------------------------------
332333
334+ /* *
335+ * @brief Converts a symbol pointer (void*) into a function pointer type without UB.
336+ *
337+ * dlsym/GetProcAddress return data pointers (void* / FARPROC). Converting those to function
338+ * pointers via reinterpret_cast is technically undefined behavior in C++.
339+ *
340+ * This helper uses memcpy to transfer the representation into a function pointer type.
341+ * If the platform uses different sizes for data pointers and function pointers, the
342+ * conversion fails and returns nullptr.
343+ *
344+ * @tparam Fn Function pointer type.
345+ * @param symbol Symbol pointer as void*.
346+ * @return Function pointer or nullptr.
347+ */
348+ template <typename Fn>
349+ auto SymbolToFunction (void * symbol) -> Fn
350+ {
351+ if (symbol == nullptr )
352+ {
353+ return nullptr ;
354+ }
355+
356+ if (sizeof (Fn) != sizeof (void *))
357+ {
358+ return nullptr ;
359+ }
360+
361+ Fn func = nullptr ;
362+ std::memcpy (&func, &symbol, sizeof (Fn));
363+ return func;
364+ }
365+
333366inline auto IsCurrentEgl (const DynamicLibrary& eglLib) -> bool
334367{
335368 if (!eglLib.IsOpen ())
@@ -338,7 +371,8 @@ inline auto IsCurrentEgl(const DynamicLibrary& eglLib) -> bool
338371 }
339372
340373 using EglGetCurrentContext = void * (*)();
341- auto func = reinterpret_cast <EglGetCurrentContext>(eglLib.GetSymbol (" eglGetCurrentContext" ));
374+ void * sym = eglLib.GetSymbol (" eglGetCurrentContext" );
375+ auto func = SymbolToFunction<EglGetCurrentContext>(sym);
342376 return func != nullptr && func () != nullptr ;
343377}
344378
@@ -352,10 +386,12 @@ inline auto IsCurrentGlx(const DynamicLibrary& glLib) -> bool
352386
353387 using GlxGetCurrentContext = void * (*)();
354388
355- auto func = reinterpret_cast <GlxGetCurrentContext>(glLib.GetSymbol (" glXGetCurrentContextARB" ));
389+ void * sym = glLib.GetSymbol (" glXGetCurrentContextARB" );
390+ auto func = SymbolToFunction<GlxGetCurrentContext>(sym);
356391 if (func == nullptr )
357392 {
358- func = reinterpret_cast <GlxGetCurrentContext>(glLib.GetSymbol (" glXGetCurrentContext" ));
393+ sym = glLib.GetSymbol (" glXGetCurrentContext" );
394+ func = SymbolToFunction<GlxGetCurrentContext>(sym);
359395 }
360396
361397 return func != nullptr && func () != nullptr ;
@@ -371,7 +407,8 @@ inline auto IsCurrentWgl() -> bool
371407 }
372408
373409 using WglGetCurrentContext = void * (WINAPI*)(void );
374- auto func = reinterpret_cast <WglGetCurrentContext>(::GetProcAddress (glModule, " wglGetCurrentContext" ));
410+ void * sym = reinterpret_cast <void *>(::GetProcAddress (glModule, " wglGetCurrentContext" ));
411+ auto func = SymbolToFunction<WglGetCurrentContext>(sym);
375412 return func != nullptr && func () != nullptr ;
376413}
377414
0 commit comments