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