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