We’ve made the last major change to the API, using bool instead of an int to return success/failure, and we’re wrapping up the last few things before we make an SDL 3.0 preview release.
If you like living on the edge now’s a great time to check out the latest code on GitHub and let us know if there are any issues!
Make sure you update your applications to check for bool return values instead of int, e.g. code that used to look like this:
The return value of Mix_Paused tells you how many channels that are paused. If you pass -1 it will check all channels, otherwise it only considers the channel that you passed as argument.
The new convention of functions returning SDL_TRUE on success and SDL_FALSE on failure causes several logic issues. These are some examples:
SDL_WaitEvent(), SDL_WaitEventTimeout(), SDL_PollEvent():
These functions are now returning SDL_TRUE if there is an event and SDL_FALSE if there is none. SDL_FALSE means failure in other functions. But from my understanding having no event is not a failure. Before this function returned just 1 if there is an event or 0 for no event. That reflected the number of events and was in line with SDL_PeepEvents() which also returns the number of events.
SDL_WaitSemaphoreTimeout():
This function now returns SDL_TRUE if no timeout occured and SDL_FALSE if it times out. This is very misleading because from the name of the function I would expect SDL_TRUE if the wait for the semaphore timed out. Furthermore from my understanding a timeout of this function is not a failure.
SDL_CursorVisible():
This function returns SDL_TRUE if the cursor is visible and SDL_FALSE if it is not. With the new convention one could suppose that the function has failed if returning SDL_FALSE. This is misleading.
There might be more of these logic issues. But those where the ones I have spotted immediately.
If we really want to keep this new convention (I prefer undoing it) I think it should be SDL_ERROR for failure and SDL_SUCCESS for success. These could be typedefed to bool. SDL_ERROR should only be used if a function really fails and sets an error string that can be retrived using SDL_GetError(). For cases like SDL_CursorVisible() we should keep SDL_TRUE and SDL_FALSE. Functions like SDL_PollEvent() should return integers and functions like SDL_WaitEventTimeout() should be re-checked for logic errors when returning SDL_TRUE and SDL_FALSE.
To be clear, the convention isn’t “every time you see SDL_bool it means success-or-failure” in the same way that when these were ints it didn’t mean every function with a numeric return was either 0 or -1.
Of course not every function returned 0 or -1. But those returning -1 (or NULL in case of returning pointers) indicated an error. I still think the current convention is confusing and not worth the trouble of porting all applications. I don‘t see any significant benefit.
I now went through all of the functions in my application and made the necessary changes. It seems to work but as expected it is chaos.
These are some of the functions I am using: SDL_Init() SDL_InitSubSystem() SDL_PeepEvents() SDL_WaitEventTimeout() SDL_PollEvent() SDL_WaitEvent() SDL_SetWindowMouseGrab() SDL_GetAudioStreamQueued() SDL_GetAudioStreamAvailable()
BEFORE the recent changes following conditions were true for all of those functions:
negative integer means that an error occurred (some functions never fail)
zero means success with no data available
positive integer means success with data available (some functions never present data)
AFTER the recent changes we got this:
Case 1: SDL_PeepEvents() SDL_GetAudioStreamQueued() SDL_GetAudioStreamAvailable()
negative integer means that an error occurred
zero means success with no data available
positive integer means success with data available
Case 2: SDL_Init() SDL_InitSubSystem() SDL_SetWindowMouseGrab()
SDL_FALSE means that an error occured
SDL_TRUE means success with no data available
Case 3: SDL_WaitEventTimeout() SDL_PollEvent() SDL_WaitEvent()
SDL_FALSE means success with no data available
SDL_TRUE means success with data available
This is chaos! Please undo this.
The only function I am using that got improved somehow is SDL_WaitSemaphoreTimeout() although I think from a linguistic point of view WaitSemaphoreTimeout true meaning that it timed out would be better than WaitSemaphoreTimeout true meaning that it did NOT time out.
Will there be windows/mac binaries? If so I may give it a try. For linux it seems like I can convert my main project to SDL3 without much difficulty. I rarely use other OSes so I don’t really want to set up an environment to build the binaries.
Personally, I like that SDL_PollEvent returns a bool because that’s how I have always used it.
while (SDL_PollEvent(&event))
{
// Handle the event...
}
This change was made before error reporting switched to using bool, probably because “no event” isn’t really an error, so I don’t think the return type of this function is relevant to the the rest of the discussion about error return types/values.
I know, but it feels a bit “ugly” to use an int like that. If the return value is basically a bool, and is intended to be used like a bool (which is the case judging from the examples), then it’s much clearer if the return type is SDL_Bool.
I don’t see why the return type needs to be consistent with SDL_PeepEvents.
They return different things so I don’t think it’s inconsistent if the return types are different. SDL_PollEvent returns whether there is an event that you need to handle. SDL_PeepEvents returns the number of events that was retrieved or added.
Another difference is that SDL_PeepEvents can fail but SDL_PollEvent cannot fail (I guess SDL_PollEvent could fail internally but it’s never reported to the caller). If SDL_PollEvent was changed so that it can report failures then I agree it should probably return an int but I’m not sure that would be extremely useful. The way I see it, SDL_PollEvent is a simple function that is used by “everyone” so it makes sense to keep it simple. SDL_PeepEvents is a more advanced function (I don’t think I have ever used it in any of my projects).
I don’t think so. The boolean type is an addition to the C language since C99. Treating integer values 0 and 1 (or any other non-zero value) as false and true existed before bool type was introduced. This post contains a short explanation: gcc - Is bool a native C type? - Stack Overflow
Note that the result of comparison operators is always 1 or 0 and the result type is int, not bool. See here: Return value of "==" operator in C - Stack Overflow
Edit: This is also true for logical operators && and ||. They return 0 or 1 as an integer value.
I think it should be consistent among ALL functions (except those returning a pointer or void of course). As mentioned above, before the recent change it was:
negative integer means that an error occurred (some functions never fail)
zero means success with no data available
positive integer means success with data available (some functions never present data)
Hmm, I normally use C++ and I forgot that using int to store boolean values was common practice in C.
In SDL2 I never liked SDL_bool because it was an enum type and int→enum conversion isn’t implicit in C++ like it is in C so it was a bit cumbersome to use. This is not an issue in SDL3.
What about functions that return types other than int or pointers?
SDL_GetPrimaryDisplay() and SDL_IOprintf() could be changed to return -1 instead of 0 on failure (if there are no special conditions that need to be considered). Edit: Can‘t be done for SDL_IOprintf() because size_t is unsigned.
SDL_AtomicAdd() is a special case as are functions that return floats.
There are some functions like SDL_CursorVisible() where returning bools can be considered.
As with most rules there will be some exemptions. Edit: Generally -1 should only be used when details on an error can be obtained using SDL_GetError().
SDL_SetRenderClipRect doesn’t accept SDL_FRect. In a few places I use a rect to fill a rect, draw the outline (without modifying it) and set the cliprect, however SDL_SetRenderClipRect is the only one of these that doesn’t accept SDL_FRect.
With SDL2 I would run my app and it would start in fullscreen. Now I see it drawing the original resolution, drawing the border as fullscreen without painting the window, then it’ll render the box. I’m not sure if I need to change my code or if that’s a bug?
Going from SDL_RenderSetLogicalSize to SDL_SetRenderLogicalPresentation broke my code. I’m not sure what I did wrong but the mouse XY isn’t matching up. I made the logic size twice the width/height, it looks like its rendering how I expected but I need to move the X and Y to double for it to match what I expect which is wrong. I could have made a mistake somewhere. I spent <80mins on the port so it’s likely I made mistakes