summaryrefslogtreecommitdiffstats
path: root/src/common/library.h
blob: 97500ac9ee71e78688508c448f136717fc930b21 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#pragma once

#include "fastfetch.h"

#ifndef FF_DISABLE_DLOPEN

    #if defined(_WIN32)
        #define FF_DLOPEN_FLAGS 0
FF_A_NODISCARD void* dlopen(const char* path, int mode);
FF_A_NODISCARD void* dlsym(void* handle, const char* symbol);
int dlclose(void* handle);
    #else
        #include <dlfcn.h>
    #endif

    #ifdef _WIN32
        #define FF_LIBRARY_EXTENSION ".dll"
    #elif defined(__APPLE__)
        #define FF_LIBRARY_EXTENSION ".dylib"
    #else
        #define FF_LIBRARY_EXTENSION ".so"
    #endif

static inline void ffLibraryUnload(void** handle) {
    assert(handle);
    if (*handle) {
        dlclose(*handle);
    }
}

    #if __cplusplus
        #define __auto_type auto
    #endif

    #define FF_LIBRARY_SYMBOL(symbolName) \
        __typeof__(&symbolName) ff##symbolName;

    #define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...)                                  \
        void* FF_A_CLEANUP(ffLibraryUnload) libraryObjectName = ffLibraryLoad(__VA_ARGS__, NULL); \
        if (libraryObjectName == NULL)                                                            \
            return returnValue;

    #define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
        FF_LIBRARY_LOAD(libraryObjectName, "dlopen(" libraryFileName ") failed", libraryFileName, maxVersion, ##__VA_ARGS__)

    #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
        symbolMapping = (__typeof__(&symbolName)) dlsym(library, #symbolName);              \
        if (symbolMapping == NULL)                                                          \
            return returnValue;

    #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
        __auto_type FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, returnValue);

    #define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
        __auto_type ff##symbolName = (__typeof__(&symbolName)) dlsym(library, #symbolName);

    #define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
        __auto_type FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, "dlsym " #symbolName " failed");

    #define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, returnValue);

    #define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, "dlsym " #symbolName " failed");

    #define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);

void* ffLibraryLoad(const char* path, int maxVersion, ...);

#else

    #define FF_LIBRARY_EXTENSION ""

    #define FF_LIBRARY_SYMBOL(symbolName) \
        __typeof__(&symbolName) ff##symbolName;

    #define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
        FF_A_UNUSED void* libraryObjectName = NULL; // Placeholder

    #define FF_LIBRARY_LOAD_MESSAGE(libraryObjectName, libraryFileName, maxVersion, ...) \
        FF_LIBRARY_LOAD(libraryObjectName, , libraryFileName, maxVersion, ##__VA_ARGS__)

    #define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
        symbolMapping = (__typeof__(&symbolName)) &symbolName;

    #define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
        FF_A_UNUSED __auto_type FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, returnValue);

    #define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
        FF_A_UNUSED __auto_type ff##symbolName = (__typeof__(&symbolName)) &symbolName;

    #define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
        FF_A_UNUSED __auto_type FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff##symbolName, symbolName, "dlsym " #symbolName " failed");

    #define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, returnValue);

    #define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff##symbolName, symbolName, "dlsym " #symbolName " failed");

    #define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
        FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff##symbolName, symbolName, returnValue);

#endif

#if _WIN32
void* ffLibraryGetModule(const wchar_t* libraryFileName);
#endif