From 33366b0a4ecc190efb9dcf2607dfb50958aa2aeb Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 11 Oct 2024 23:04:00 +0200 Subject: [PATCH] Fix SDL_MAIN_USE_CALLBACKS with Android, introduce SDL_MAIN_EXPORTED My simplification of the conditions for including SDL_main_impl.h had one problem: I forgot that SDL_main_impl.h must be included even on Android when SDL_MAIN_USE_CALLBACKS is used, because then a SDL_main() function that makes sure the callbacks get called is needed, and that function is implemented in SDL_main_impl.h But OTOH, even when SDL_MAIN_USE_CALLBACKS is used, SDL_main_impl.h should not implement a standard `int main(...)` function on Android (because there the SDL-using native code is compiled as a library and the entry point is in SDLActivity.java, which calls SDL_main() in said library). So the check for platforms that don't have *any* native main function but just SDL_main() called from the outside should be handled in SDL_main_impl.h, so both the normal and the callback case can avoid generating a standard main() in the same way. To do this, SDL_MAIN_EXPORTED is defined for platforms like Android, where the real entry point (main() function) is outside of the code that uses SDL, so - SDL_main() must be visibly exported with SDL_DECLSPEC, so the outside code can call it - SDL_main_impl.h must not implement a "real" main() function Another small change based on this is defining SDLMAIN_DECLSPEC at a more general place. If another platform like Android (where the entry point is somewhere else entirely, possibly implemented in a different programming language) turns up, defining SDL_MAIN_NEEDED (so the users main() is renamed to SDL_main()) and SDL_MAIN_EXPORTED should be all that's needed on the SDL_main.h side - and if not then at least the implementation is cleaner and clearer now, IMHO. fixes #11162 --- include/SDL3/SDL_main.h | 29 +++++++++++++++++------------ include/SDL3/SDL_main_impl.h | 7 ++++--- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 6160e5e364e61..52fc8150ff751 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -86,8 +86,14 @@ */ #define SDL_MAIN_NEEDED - /* We need to export SDL_main so it can be launched from Java */ - #define SDLMAIN_DECLSPEC SDL_DECLSPEC + /* As this is launched from Java, the real entry point (main() function) + is outside of the the binary built from this code. + This define makes sure that, unlike on other platforms, SDL_main.h + and SDL_main_impl.h export an `SDL_main()` function (to be called + from Java), but don't implement a native `int main(int argc, char* argv[])` + or similar. + */ + #define SDL_MAIN_EXPORTED #elif defined(SDL_PLATFORM_EMSCRIPTEN) /* On Emscripten, SDL provides a main function that converts URL @@ -134,9 +140,14 @@ #endif #endif /* SDL_MAIN_HANDLED */ -#ifndef SDLMAIN_DECLSPEC +#ifdef SDL_MAIN_EXPORTED +/* We need to export SDL_main so it can be launched from external code, + like SDLActivity.java on Android */ +#define SDLMAIN_DECLSPEC SDL_DECLSPEC +#else +/* usually this is empty */ #define SDLMAIN_DECLSPEC -#endif +#endif /* SDL_MAIN_EXPORTED */ #ifdef SDL_WIKI_DOCUMENTATION_SECTION @@ -562,14 +573,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #include #if !defined(SDL_MAIN_HANDLED) && !defined(SDL_MAIN_NOIMPL) - /* include header-only SDL_main implementations - * Note: currently Android is the only platform where we rename main() to SDL_main() but - * do *not* use SDL_main_impl.h (because SDL_main() is called from external Java code). - * If other platforms like that turn up, add them next to "defined(SDL_PLATFORM_ANDROID)" - */ - #if (defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)) && \ - !defined(SDL_PLATFORM_ANDROID) - + /* include header-only SDL_main implementations */ + #if defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) /* platforms which main (-equivalent) can be implemented in plain C */ #include #endif diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index 950b750bc7a82..0c19d2b3e27a5 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -29,7 +29,7 @@ #endif /* if someone wants to include SDL_main.h but doesn't want the main handing magic, - (maybe to call SDL_RegisterApp()) they can #define SDL_MAIN_HANDLED first + (maybe to call SDL_RegisterApp()) they can #define SDL_MAIN_HANDLED first. SDL_MAIN_NOIMPL is for SDL-internal usage (only affects implementation, not definition of SDL_MAIN_AVAILABLE etc in SDL_main.h) and if the user wants to have the SDL_main implementation (from this header) in another source file @@ -64,8 +64,9 @@ #endif /* SDL_MAIN_USE_CALLBACKS */ - /* set up the usual SDL_main stuff if we're not using callbacks or if we are but need the normal entry point. */ - #if !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) + /* set up the usual SDL_main stuff if we're not using callbacks or if we are but need the normal entry point, + unless the real entry point needs to be somewhere else entirely, like Android where it's in Java code */ + #if (!defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD)) && !defined(SDL_MAIN_EXPORTED) #if defined(SDL_PLATFORM_WINDOWS)