SDL 3.0
SDL_begin_code.h
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22/* WIKI CATEGORY: BeginCode */
23
24/**
25 * # CategoryBeginCode
26 *
27 * `SDL_begin_code.h` sets things up for C dynamic library function
28 * definitions, static inlined functions, and structures aligned at 4-byte
29 * alignment. If you don't like ugly C preprocessor code, don't look at this
30 * file. :)
31 *
32 * SDL's headers use this; applications generally should not include this
33 * header directly.
34 */
35
36/* This shouldn't be nested -- included it around code only. */
37#ifdef SDL_begin_code_h
38#error Nested inclusion of SDL_begin_code.h
39#endif
40#define SDL_begin_code_h
41
42#ifdef SDL_WIKI_DOCUMENTATION_SECTION
43
44/**
45 * A macro to tag a symbol as deprecated.
46 *
47 * A function is marked deprecated by adding this macro to its declaration:
48 *
49 * ```c
50 * extern SDL_DEPRECATED int ThisFunctionWasABadIdea(void);
51 * ```
52 *
53 * Compilers with deprecation support can give a warning when a deprecated
54 * function is used. This symbol may be used in SDL's headers, but apps are
55 * welcome to use it for their own interfaces as well.
56 *
57 * SDL, on occasion, might deprecate a function for various reasons. However,
58 * SDL never removes symbols before major versions, so deprecated interfaces
59 * in SDL3 will remain available until SDL4, where it would be expected an app
60 * would have to take steps to migrate anyhow.
61 *
62 * On compilers without a deprecation mechanism, this is defined to nothing,
63 * and using a deprecated function will not generate a warning.
64 *
65 * \since This macro is available since SDL 3.2.0.
66 */
67#define SDL_DEPRECATED __attribute__((deprecated))
68
69/**
70 * A macro to tag a symbol as a public API.
71 *
72 * SDL uses this macro for all its public functions. On some targets, it is
73 * used to signal to the compiler that this function needs to be exported from
74 * a shared library, but it might have other side effects.
75 *
76 * This symbol is used in SDL's headers, but apps and other libraries are
77 * welcome to use it for their own interfaces as well.
78 *
79 * \since This macro is available since SDL 3.2.0.
80 */
81#define SDL_DECLSPEC __attribute__ ((visibility("default")))
82
83/**
84 * A macro to set a function's calling conventions.
85 *
86 * SDL uses this macro for all its public functions, and any callbacks it
87 * defines. This macro guarantees that calling conventions match between SDL
88 * and the app, even if the two were built with different compilers or
89 * optimization settings.
90 *
91 * When writing a callback function, it is very important for it to be
92 * correctly tagged with SDLCALL, as mismatched calling conventions can cause
93 * strange behaviors and can be difficult to diagnose. Plus, on many
94 * platforms, SDLCALL is defined to nothing, so compilers won't be able to
95 * warn that the tag is missing.
96 *
97 * This symbol is used in SDL's headers, but apps and other libraries are
98 * welcome to use it for their own interfaces as well.
99 *
100 * \since This macro is available since SDL 3.2.0.
101 */
102#define SDLCALL __cdecl
103
104/**
105 * A macro to request a function be inlined.
106 *
107 * This is a hint to the compiler to inline a function. The compiler is free
108 * to ignore this request. On compilers without inline support, this is
109 * defined to nothing.
110 *
111 * \since This macro is available since SDL 3.2.0.
112 */
113#define SDL_INLINE __inline
114
115/**
116 * A macro to demand a function be inlined.
117 *
118 * This is a command to the compiler to inline a function. SDL uses this macro
119 * in its public headers for a handful of simple functions. On compilers
120 * without forceinline support, this is defined to `static SDL_INLINE`, which
121 * is often good enough.
122 *
123 * This symbol is used in SDL's headers, but apps and other libraries are
124 * welcome to use it for their own interfaces as well.
125 *
126 * \since This macro is available since SDL 3.2.0.
127 */
128#define SDL_FORCE_INLINE __forceinline
129
130/**
131 * A macro to tag a function as never-returning.
132 *
133 * This is a hint to the compiler that a function does not return. An example
134 * of a function like this is the C runtime's exit() function.
135 *
136 * This hint can lead to code optimizations, and help analyzers understand
137 * code flow better. On compilers without noreturn support, this is defined to
138 * nothing.
139 *
140 * This symbol is used in SDL's headers, but apps and other libraries are
141 * welcome to use it for their own interfaces as well.
142 *
143 * \since This macro is available since SDL 3.2.0.
144 */
145#define SDL_NORETURN __attribute__((noreturn))
146
147/**
148 * A macro to tag a function as never-returning (for analysis purposes).
149 *
150 * This is almost identical to SDL_NORETURN, except functions marked with this
151 * _can_ actually return. The difference is that this isn't used for code
152 * generation, but rather static analyzers use this information to assume
153 * truths about program state and available code paths. Specifically, this tag
154 * is useful for writing an assertion mechanism. Indeed, SDL_assert uses this
155 * tag behind the scenes. Generally, apps that don't understand the specific
156 * use-case for this tag should avoid using it directly.
157 *
158 * On compilers without analyzer_noreturn support, this is defined to nothing.
159 *
160 * This symbol is used in SDL's headers, but apps and other libraries are
161 * welcome to use it for their own interfaces as well.
162 *
163 * \since This macro is available since SDL 3.2.0.
164 */
165#define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
166
167
168/**
169 * A macro to signal that a case statement without a `break` is intentional.
170 *
171 * C compilers have gotten more aggressive about warning when a switch's
172 * `case` block does not end with a `break` or other flow control statement,
173 * flowing into the next case's code, as this is a common accident that leads
174 * to strange bugs. But sometimes falling through to the next case is the
175 * correct and desired behavior. This symbol lets an app communicate this
176 * intention to the compiler, so it doesn't generate a warning.
177 *
178 * It is used like this:
179 *
180 * ```c
181 * switch (x) {
182 * case 1:
183 * DoSomethingOnlyForOne();
184 * SDL_FALLTHROUGH; // tell the compiler this was intentional.
185 * case 2:
186 * DoSomethingForOneAndTwo();
187 * break;
188 * }
189 * ```
190 *
191 * \since This macro is available since SDL 3.2.0.
192 */
193#define SDL_FALLTHROUGH [[fallthrough]]
194
195/**
196 * A macro to tag a function's return value as critical.
197 *
198 * This is a hint to the compiler that a function's return value should not be
199 * ignored.
200 *
201 * If an NODISCARD function's return value is thrown away (the function is
202 * called as if it returns `void`), the compiler will issue a warning.
203 *
204 * While it's generally good practice to check return values for errors, often
205 * times legitimate programs do not for good reasons. Be careful about what
206 * functions are tagged as NODISCARD. It operates best when used on a function
207 * that's failure is surprising and catastrophic; a good example would be a
208 * program that checks the return values of all its file write function calls
209 * but not the call to close the file, which it assumes incorrectly never
210 * fails.
211 *
212 * Function callers that want to throw away a NODISCARD return value can call
213 * the function with a `(void)` cast, which informs the compiler the act is
214 * intentional.
215 *
216 * On compilers without nodiscard support, this is defined to nothing.
217 *
218 * \since This macro is available since SDL 3.2.0.
219 */
220#define SDL_NODISCARD [[nodiscard]]
221
222/**
223 * A macro to tag a function as an allocator.
224 *
225 * This is a hint to the compiler that a function is an allocator, like
226 * malloc(), with certain rules. A description of how GCC treats this hint is
227 * here:
228 *
229 * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
230 *
231 * On compilers without allocator tag support, this is defined to nothing.
232 *
233 * Most apps don't need to, and should not, use this directly.
234 *
235 * \since This macro is available since SDL 3.2.0.
236 */
237#define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
238
239/**
240 * A macro to tag a function as returning a certain allocation.
241 *
242 * This is a hint to the compiler that a function allocates and returns a
243 * specific amount of memory based on one of its arguments. For example, the C
244 * runtime's malloc() function could use this macro with an argument of 1
245 * (first argument to malloc is the size of the allocation).
246 *
247 * On compilers without alloc_size support, this is defined to nothing.
248 *
249 * Most apps don't need to, and should not, use this directly.
250 *
251 * \since This macro is available since SDL 3.2.0.
252 */
253#define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
254
255/**
256 * A macro to tag a pointer variable, to help with pointer aliasing.
257 *
258 * A good explanation of the restrict keyword is here:
259 *
260 * https://en.wikipedia.org/wiki/Restrict
261 *
262 * On compilers without restrict support, this is defined to nothing.
263 *
264 * \since This macro is available since SDL 3.4.0.
265 */
266#define SDL_RESTRICT __restrict
267
268/**
269 * Check if the compiler supports a given builtin functionality.
270 *
271 * This allows preprocessor checks for things that otherwise might fail to
272 * compile.
273 *
274 * Supported by virtually all clang versions and more-recent GCCs. Use this
275 * instead of checking the clang version if possible.
276 *
277 * On compilers without has_builtin support, this is defined to 0 (always
278 * false).
279 *
280 * \since This macro is available since SDL 3.2.0.
281 */
282#define SDL_HAS_BUILTIN(x) __has_builtin(x)
283
284/**
285 * Check if the compiler supports a given extension.
286 *
287 * This allows preprocessor checks for things that otherwise might fail to
288 * compile.
289 *
290 * Supported by virtually all clang versions and more-recent GCCs. Use this
291 * instead of checking the clang version if possible.
292 *
293 * On compilers without has_extension support, this is defined to 0 (always
294 * false).
295 *
296 * \since This macro is available since SDL 3.2.0.
297 */
298#define SDL_HAS_EXTENSION(x) __has_extension(x)
299
300/**
301 * A macro to specify data alignment.
302 *
303 * This informs the compiler that a given datatype or variable must be aligned
304 * to a specific byte count.
305 *
306 * For example:
307 *
308 * ```c
309 * // make sure this is struct is aligned to 16 bytes for SIMD access.
310 * typedef struct {
311 * float x, y, z, w;
312 * } SDL_ALIGNED(16) MySIMDAlignedData;
313 *
314 * // make sure this one field in a struct is aligned to 16 bytes for SIMD access.
315 * typedef struct {
316 * SomeStuff stuff;
317 * float SDL_ALIGNED(16) position[4];
318 * SomeOtherStuff other_stuff;
319 * } MyStruct;
320 *
321 * // make sure this variable is aligned to 32 bytes.
322 * int SDL_ALIGNED(32) myval = 0;
323 * ```
324 *
325 * Alignment is only guaranteed for things the compiler places: local
326 * variables on the stack and global/static variables. To dynamically allocate
327 * something that respects this alignment, use SDL_aligned_alloc() or some
328 * other mechanism.
329 *
330 * On compilers without alignment support, this macro is defined to an invalid
331 * symbol, to make it clear that the current compiler is likely to generate
332 * incorrect code when it sees this macro.
333 *
334 * \param x the byte count to align to, so the data's address will be a
335 * multiple of this value.
336 *
337 * \since This macro is available since SDL 3.4.0.
338 */
339#define SDL_ALIGNED(x) __attribute__((aligned(x)))
340
341/* end of wiki documentation section. */
342#endif
343
344/* `restrict` is from C99, but __restrict works with both Visual Studio and GCC. */
345#ifndef SDL_RESTRICT
346# if defined(restrict) || ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)))
347# define SDL_RESTRICT restrict
348# elif defined(_MSC_VER) || defined(__GNUC__) || defined(__clang__)
349# define SDL_RESTRICT __restrict
350# else
351# define SDL_RESTRICT
352# endif
353#endif
354
355#ifndef SDL_HAS_BUILTIN
356#ifdef __has_builtin
357#define SDL_HAS_BUILTIN(x) __has_builtin(x)
358#else
359#define SDL_HAS_BUILTIN(x) 0
360#endif
361#endif
362
363#ifndef SDL_HAS_EXTENSION
364#ifdef __has_extension
365#define SDL_HAS_EXTENSION(x) __has_extension(x)
366#else
367#define SDL_HAS_EXTENSION(x) 0
368#endif
369#endif
370
371#ifndef SDL_DEPRECATED
372# if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */
373# define SDL_DEPRECATED __attribute__((deprecated))
374# elif defined(_MSC_VER)
375# define SDL_DEPRECATED __declspec(deprecated)
376# else
377# define SDL_DEPRECATED
378# endif
379#endif
380
381#ifndef SDL_UNUSED
382# ifdef __GNUC__
383# define SDL_UNUSED __attribute__((unused))
384# else
385# define SDL_UNUSED
386# endif
387#endif
388
389/* Some compilers use a special export keyword */
390#ifndef SDL_DECLSPEC
391# if defined(SDL_PLATFORM_WINDOWS)
392# ifdef DLL_EXPORT
393# define SDL_DECLSPEC __declspec(dllexport)
394# else
395# define SDL_DECLSPEC
396# endif
397# else
398# if defined(__GNUC__) && __GNUC__ >= 4
399# define SDL_DECLSPEC __attribute__ ((visibility("default")))
400# else
401# define SDL_DECLSPEC
402# endif
403# endif
404#endif
405
406/* By default SDL uses the C calling convention */
407#ifndef SDLCALL
408#if defined(SDL_PLATFORM_WINDOWS) && !defined(__GNUC__)
409#define SDLCALL __cdecl
410#else
411#define SDLCALL
412#endif
413#endif /* SDLCALL */
414
415/* Force structure packing at 4 byte alignment.
416 This is necessary if the header is included in code which has structure
417 packing set to an alternate value, say for loading structures from disk.
418 The packing is reset to the previous value in SDL_close_code.h
419 */
420#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
421#ifdef _MSC_VER
422#pragma warning(disable: 4103)
423#endif
424#ifdef __clang__
425#pragma clang diagnostic ignored "-Wpragma-pack"
426#endif
427#ifdef __BORLANDC__
428#pragma nopackwarning
429#endif
430#ifdef _WIN64
431/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
432#pragma pack(push,8)
433#else
434#pragma pack(push,4)
435#endif
436#endif /* Compiler needs structure packing set */
437
438#ifndef SDL_INLINE
439#ifdef __GNUC__
440#define SDL_INLINE __inline__
441#elif defined(_MSC_VER) || defined(__BORLANDC__) || \
442 defined(__DMC__) || defined(__SC__) || \
443 defined(__WATCOMC__) || defined(__LCC__) || \
444 defined(__DECC) || defined(__CC_ARM)
445#define SDL_INLINE __inline
446#ifndef __inline__
447#define __inline__ __inline
448#endif
449#else
450#define SDL_INLINE inline
451#ifndef __inline__
452#define __inline__ inline
453#endif
454#endif
455#endif /* SDL_INLINE not defined */
456
457#ifndef SDL_FORCE_INLINE
458#if defined(_MSC_VER) && (_MSC_VER >= 1200)
459#define SDL_FORCE_INLINE __forceinline
460#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
461#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
462#else
463#define SDL_FORCE_INLINE static SDL_INLINE
464#endif
465#endif /* SDL_FORCE_INLINE not defined */
466
467#ifndef SDL_NORETURN
468#if defined(__GNUC__)
469#define SDL_NORETURN __attribute__((noreturn))
470#elif defined(_MSC_VER)
471#define SDL_NORETURN __declspec(noreturn)
472#else
473#define SDL_NORETURN
474#endif
475#endif /* SDL_NORETURN not defined */
476
477#ifdef __clang__
478#if __has_feature(attribute_analyzer_noreturn)
479#define SDL_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
480#endif
481#endif
482
483#ifndef SDL_ANALYZER_NORETURN
484#define SDL_ANALYZER_NORETURN
485#endif
486
487/* Apparently this is needed by several Windows compilers */
488#ifndef __MACH__
489#ifndef NULL
490#ifdef __cplusplus
491#define NULL 0
492#else
493#define NULL ((void *)0)
494#endif
495#endif /* NULL */
496#endif /* __MACH__ */
497
498#ifndef SDL_FALLTHROUGH
499#if (defined(__cplusplus) && __cplusplus >= 201703L) || \
500 (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L)
501#define SDL_FALLTHROUGH [[fallthrough]]
502#else
503#if defined(__has_attribute) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
504#define SDL_HAS_FALLTHROUGH __has_attribute(__fallthrough__)
505#else
506#define SDL_HAS_FALLTHROUGH 0
507#endif /* __has_attribute */
508#if SDL_HAS_FALLTHROUGH && \
509 ((defined(__GNUC__) && __GNUC__ >= 7) || \
510 (defined(__clang_major__) && __clang_major__ >= 10))
511#define SDL_FALLTHROUGH __attribute__((__fallthrough__))
512#else
513#define SDL_FALLTHROUGH do {} while (0) /* fallthrough */
514#endif /* SDL_HAS_FALLTHROUGH */
515#undef SDL_HAS_FALLTHROUGH
516#endif /* C++17 or C2x */
517#endif /* SDL_FALLTHROUGH not defined */
518
519#ifndef SDL_NODISCARD
520#if (defined(__cplusplus) && __cplusplus >= 201703L) || \
521 (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
522#define SDL_NODISCARD [[nodiscard]]
523#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
524#define SDL_NODISCARD __attribute__((warn_unused_result))
525#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
526#define SDL_NODISCARD _Check_return_
527#else
528#define SDL_NODISCARD
529#endif /* C++17 or C23 */
530#endif /* SDL_NODISCARD not defined */
531
532#ifndef SDL_MALLOC
533#if defined(__GNUC__) && (__GNUC__ >= 3)
534#define SDL_MALLOC __attribute__((malloc))
535/** FIXME
536#elif defined(_MSC_VER)
537#define SDL_MALLOC __declspec(allocator) __desclspec(restrict)
538**/
539#else
540#define SDL_MALLOC
541#endif
542#endif /* SDL_MALLOC not defined */
543
544#ifndef SDL_ALLOC_SIZE
545#if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
546#define SDL_ALLOC_SIZE(p) __attribute__((alloc_size(p)))
547#elif defined(_MSC_VER)
548#define SDL_ALLOC_SIZE(p)
549#else
550#define SDL_ALLOC_SIZE(p)
551#endif
552#endif /* SDL_ALLOC_SIZE not defined */
553
554#ifndef SDL_ALLOC_SIZE2
555#if (defined(__clang__) && __clang_major__ >= 4) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
556#define SDL_ALLOC_SIZE2(p1, p2) __attribute__((alloc_size(p1, p2)))
557#elif defined(_MSC_VER)
558#define SDL_ALLOC_SIZE2(p1, p2)
559#else
560#define SDL_ALLOC_SIZE2(p1, p2)
561#endif
562#endif /* SDL_ALLOC_SIZE2 not defined */
563
564#ifndef SDL_ALIGNED
565#if defined(__clang__) || defined(__GNUC__)
566#define SDL_ALIGNED(x) __attribute__((aligned(x)))
567#elif defined(_MSC_VER)
568#define SDL_ALIGNED(x) __declspec(align(x))
569#elif defined(__cplusplus) && (__cplusplus >= 201103L)
570#define SDL_ALIGNED(x) alignas(x)
571#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
572#define SDL_ALIGNED(x) _Alignas(x)
573#else
574#define SDL_ALIGNED(x) PLEASE_DEFINE_SDL_ALIGNED
575#endif
576#endif /* SDL_ALIGNED not defined */
577