ohmu
·
2026-10-15
1#pragma once
2
3#include "fastfetch.h" // IWYU pragma: keep
4
5#ifndef FF_DISABLE_DLOPEN
6
7 #if defined(_WIN32)
8 #define FF_DLOPEN_FLAGS 0
9[[nodiscard]] void* dlopen(const char* path, int mode);
10[[nodiscard]] void* dlsym(void* handle, const char* symbol);
11int dlclose(void* handle);
12 #else
13 #include <dlfcn.h>
14 #endif
15
16 #ifdef _WIN32
17 #define FF_LIBRARY_EXTENSION ".dll"
18 #elif defined(__APPLE__)
19 #define FF_LIBRARY_EXTENSION ".dylib"
20 #else
21 #define FF_LIBRARY_EXTENSION ".so"
22 #endif
23
24[[gnu::nonnull(1)]] static inline void ffLibraryUnload(void** handle) {
25 if (*handle) {
26 dlclose(*handle);
27 }
28}
29
30 #define FF_LIBRARY_SYMBOL(symbolName) \
31 typeof(&symbolName) ff##symbolName;
32
33 #define FF_LIBRARY_LOAD(libraryObjectName, returnValue, libraryFileName, maxVersion, ...) \
34 [[gnu::cleanup(ffLibraryUnload)]] void* libraryObjectName = ffLibraryLoadSingle(libraryFileName, maxVersion); \
35 __VA_OPT__(if (__builtin_expect(libraryObjectName == nullptr, false)) libraryObjectName = ffLibraryLoadMulti(__VA_ARGS__, nullptr);) \
36 if (__builtin_expect(libraryObjectName == nullptr, false)) \
37 return returnValue;
38
39 #define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
40 FF_LIBRARY_LOAD(libraryObjectName, "dlopen(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)
41
42 #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
43 symbolMapping = (typeof(&symbolName)) dlsym(library, #symbolName); \
44 if (__builtin_expect(symbolMapping == nullptr, false)) \
45 return returnValue;
46
47 #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
48 auto FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, returnValue);
49
50 #define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
51 auto ff##symbolName = (typeof(&symbolName)) dlsym(library, #symbolName);
52
53 #define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
54 auto FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, "dlsym " #symbolName " failed");
55
56 #define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
57 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, returnValue);
58
59 #define FF_LIBRARY_LOAD_SYMBOL_VAR_LAZY(library, varName, symbolName) \
60 (varName).ff##symbolName = (typeof(&symbolName)) dlsym(library, #symbolName);
61
62 #define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
63 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, "dlsym " #symbolName " failed");
64
65 #define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
66 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);
67
68[[gnu::nonnull(1), nodiscard]] void* ffLibraryLoadSingle(const char* path, int maxVersion);
69[[gnu::nonnull(1), nodiscard]] void* ffLibraryLoadMulti(const char* path, int maxVersion, ...);
70
71#else
72
73 #define FF_LIBRARY_EXTENSION ""
74
75 #define FF_LIBRARY_SYMBOL(symbolName) \
76 typeof(&symbolName) ff##symbolName;
77
78 #define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
79 [[maybe_unused]] void* libraryObjectName = nullptr; // Placeholder
80
81 #define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
82 FF_LIBRARY_LOAD(libraryObjectName, , libraryFileName, maxVersion, ##__VA_ARGS__)
83
84 #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
85 symbolMapping = (typeof(&symbolName)) &symbolName;
86
87 #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
88 [[maybe_unused]] auto FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, returnValue);
89
90 #define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
91 [[maybe_unused]] auto ff##symbolName = (typeof(&symbolName)) &symbolName;
92
93 #define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
94 [[maybe_unused]] auto FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, "dlsym " #symbolName " failed");
95
96 #define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
97 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, returnValue);
98
99 #define FF_LIBRARY_LOAD_SYMBOL_VAR_LAZY(library, varName, symbolName) \
100 (varName).ff##symbolName = (typeof(&symbolName)) &symbolName;
101
102 #define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
103 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, "dlsym " #symbolName " failed");
104
105 #define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
106 FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);
107
108#endif
109
110#if _WIN32
111[[gnu::nonnull(1), nodiscard]] void* ffLibraryGetModule(const wchar_t* libraryFileName);
112#endif
113
114// Return false to stop iterating, true to continue
115typedef bool (*FFLibraryIterateCallback)(const char* name, void* userData);
116// Iterate over all loaded dynamic libraries. Returns true on success, false on failure.
117[[nodiscard]] bool ffLibraryIterateDynamicLibs(FFLibraryIterateCallback callback, void* userData);