Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
PluginMacros.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Common/CompilerMacrosType.h"
5#include "../Common/PrimitiveDefinitions.h"
6#include "../Memory/Memory.h" // OPTIONAL DEPENDENCY
7#include "PluginHash.h"
8
9//
10// SC_PLUGIN_EXPORT
11//
12
13#if SC_COMPILER_MSVC || SC_COMPILER_CLANG_CL
14#define SC_PLUGIN_EXPORT __declspec(dllexport)
15#else
16#define SC_PLUGIN_EXPORT __attribute__((visibility("default")))
17#endif
18
19#if SC_PLUGIN_LIBRARY
20#define SC_PLUGIN_LINKER_OPERATORS \
21 void* operator new(SC::size_t len) { return SC::Memory::allocate(len, 8); } \
22 void* operator new[](SC::size_t len) { return SC::Memory::allocate(len, 8); } \
23 void operator delete(void* p, SC::size_t) noexcept \
24 { \
25 if (p != 0) \
26 { \
27 SC::Memory::release(p); \
28 } \
29 } \
30 void operator delete(void* p) noexcept \
31 { \
32 if (p != 0) \
33 { \
34 SC::Memory::release(p); \
35 } \
36 }
37
38#if SC_COMPILER_MSVC
39#define SC_PLUGIN_LINKER_DEFINITIONS \
40 SC_PLUGIN_LINKER_OPERATORS \
41 extern "C" void __CxxFrameHandler4() {} \
42 extern "C" void __CxxFrameHandler3() {} \
43 int __stdcall DllMain(void*, unsigned int, void*) { return 1; } \
44 extern "C" int _fltused = 0;
45#else
46// Cannot use builtin like __builtin_bzero as they will generate an infinite loop
47// We also use inline asm to disable optimizations
48// See: https://nullprogram.com/blog/2023/02/15/
49// TODO: Check if we can link libc without a sysroot on macOS to get rid of these
50#define SC_PLUGIN_LINKER_DEFINITIONS \
51 SC_PLUGIN_LINKER_OPERATORS \
52 extern "C" void bzero(void* s, SC::size_t n) \
53 { \
54 unsigned char* p = reinterpret_cast<unsigned char*>(s); \
55 while (n-- > 0) \
56 { \
57 *p++ = 0; \
58 } \
59 } \
60 extern "C" int memcmp(const void* s1, const void* s2, SC::size_t n) \
61 { \
62 const unsigned char* p1 = reinterpret_cast<const unsigned char*>(s1); \
63 const unsigned char* p2 = reinterpret_cast<const unsigned char*>(s2); \
64 while (n--) \
65 { \
66 if (*p1 < *p2) \
67 { \
68 return -1; \
69 } \
70 else if (*p1 > *p2) \
71 { \
72 return 1; \
73 } \
74 } \
75 return 0; \
76 } \
77 extern "C" int __cxa_guard_acquire(SC::uint64_t* guard_object) \
78 { \
79 if (*reinterpret_cast<const SC::uint8_t*>(guard_object) != 0) \
80 return 0; \
81 return 1; \
82 } \
83 extern "C" void __cxa_guard_release(SC::uint64_t* guard_object) \
84 { \
85 *reinterpret_cast<SC::uint8_t*>(guard_object) = 1; \
86 }
87
88#endif
89#else
90#define SC_PLUGIN_LINKER_DEFINITIONS
91#endif
92
93//
94// SC_PLUGIN_DEFINE
95//
96#define SC_PLUGIN_DEFINE(PluginName) \
97 SC_PLUGIN_LINKER_DEFINITIONS \
98 extern "C" SC_PLUGIN_EXPORT bool PluginName##Init(PluginName*& instance) \
99 { \
100 instance = new PluginName(); \
101 return instance->init(); \
102 } \
103 \
104 extern "C" SC_PLUGIN_EXPORT bool PluginName##Close(PluginName* instance) \
105 { \
106 auto res = instance->close(); \
107 delete instance; \
108 return res; \
109 }
110
111#define SC_PLUGIN_EXPORT_INTERFACES(PluginName, ...) \
112 extern "C" SC_PLUGIN_EXPORT bool PluginName##QueryInterface(PluginName* plugin, SC::uint32_t hash, \
113 void** pluginInterface) \
114 { \
115 return SC::PluginCastInterface<PluginName, __VA_ARGS__>()(plugin, hash, pluginInterface); \
116 }
117
118#if !DOXYGEN
119namespace SC
120{
121template <typename PluginClass, typename... InterfaceClasses>
122struct PluginCastInterface;
123
124template <typename PluginClass>
125struct PluginCastInterface<PluginClass>
126{
127 bool operator()(PluginClass*, uint32_t, void**) { return false; }
128};
129
130template <typename PluginClass, typename InterfaceClass, typename... InterfaceClasses>
131struct PluginCastInterface<PluginClass, InterfaceClass, InterfaceClasses...>
132{
133 bool operator()(PluginClass* plugin, uint32_t hash, void** pluginInterface)
134 {
135 if (hash == InterfaceClass::InterfaceHash)
136 {
137 *pluginInterface = static_cast<InterfaceClass*>(plugin);
138 return true;
139 }
140 return PluginCastInterface<PluginClass, InterfaceClasses...>()(plugin, hash, pluginInterface);
141 }
142};
143#endif
144} // namespace SC