I have already seen several demo programs, including the SDL3 tests, which use functions like SDL_Appxxx(…)
.
Does anyone have any idea how to compile such programs?
gcc main.c -o main -lSDL3
it does not work. Then he complains that the main() is missing.
It works for me. Did you remember to define the macro SDL_MAIN_USE_CALLBACKS
before including <SDL3/SDL_main.h>
? It’s all explained here.
1 Like
Thanks to your link I have come one step further.
This line is very important.
#define SDL_MAIN_USE_CALLBACKS
I wanted to try the following examples and they are missing everywhere.
Now it can be compiled as follows.
g++ main_GLSE.c -lSDL3 -lGL
It just doesn’t seem to work with pure c.
Is there also a way to make it work with gcc?
8Observer8’s examples are written in C++ which is why you have to use g++
rather than gcc
.
I banned all the C++ stuff, now it works with simple C too.
// g++ main.c -o main -lSDL3
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
struct AppContext {
SDL_Window* window;
SDL_Renderer* renderer;
SDL_bool app_quit;
} appContext;
int SDL_Fail(){
SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
return -1;
}
int SDL_AppInit(void** appstate, int argc, char* argv[]) {
// init the library, here we make a window so we only need the Video capabilities.
if (SDL_Init(SDL_INIT_VIDEO)){
return SDL_Fail();
}
// create a window
SDL_Window* window = SDL_CreateWindow("Window", 352, 430, SDL_WINDOW_RESIZABLE);
if (!window){
return SDL_Fail();
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
if (!renderer){
return SDL_Fail();
}
// print some information about the window
SDL_ShowWindow(window);
{
int width, height, bbwidth, bbheight;
SDL_GetWindowSize(window, &width, &height);
SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight);
SDL_Log("Window size: %ix%i", width, height);
SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
if (width != bbwidth){
SDL_Log("This is a highdpi environment.");
}
}
appContext.window = window;
appContext.renderer = renderer;
appContext.app_quit=SDL_FALSE;
*appstate = &appContext;
SDL_Log("Application started successfully!");
return 0;
}
int SDL_AppEvent(void *appstate, const SDL_Event* event) {
struct AppContext *app = appstate;
if (event->type == SDL_EVENT_QUIT) {
app->app_quit = SDL_TRUE;
}
return 0;
}
int SDL_AppIterate(void *appstate) {
struct AppContext *app = appstate;
// draw a color
float time = SDL_GetTicks() / 1000.f;
int red = (SDL_sin(time) + 1) / 2.0 * 255;
int green = (SDL_sin(time / 2) + 1) / 2.0 * 255;
int blue = (SDL_sin(time) * 2 + 1) / 2.0 * 255;
SDL_SetRenderDrawColor(app->renderer, red, green, blue, SDL_ALPHA_OPAQUE);
SDL_RenderClear(app->renderer);
SDL_RenderPresent(app->renderer);
return app->app_quit;
}
void SDL_AppQuit(void* appstate) {
struct AppContext *app = appstate;
if (app) {
SDL_DestroyRenderer(app->renderer);
SDL_DestroyWindow(app->window);
}
SDL_Quit();
SDL_Log("Application quit successfully!");
}
If I understand correctly, somewhere in the libSDL3 is the main(…) ?
In which there is an SDL_EnterAppMainCallbacks(…) and which calls my functions?
Yes, SDL_main.h includes SDL_main_impl.h which defines the main function.
I took a closer look at SDL_main_impl.h.
This can be seen in the various start routines such as main() or WinMain(), which all call SDL_RunApp.
I still noticed an extreme difference between SDL2 and SDL3. With SDL3, a simple main() also works under Windows and SDL2 requires a WinMain().
It’s probably better that you read the docs if you want to know how it’s supposed to be used because that particular header uses a lot of macro magic.
SDL2 does not require you to define WinMain. That’s the whole point behind SDL_main.
The headers might look widely different in SDL2 and SDL3 but the way you use them is very similar.
In both SDL2 and SDL3, you define your main function as:
int main(int argc, char *argv[])
The difference is:
- In SDL2 you just include
SDL.h
like normal but you have to link the SDL2_main library on Windows.
- In SDL3 you have to include
SDL_main.h
in the file that contains the main function but you don’t need to link any additional libraries.
Basically, how it works is that SDL defines a macro named main
that expands to SDL_main
so when you define your main function you are actually defining a function named SDL_main
. SDL defines it’s own main function (main
, WinMain
, or whatever the platform requires) that calls SDL_main
(The SDL_RunApp
function that you saw calls SDL_main
internally).
If you define SDL_MAIN_USE_CALLBACKS
in SDL3 then SDL will define its own SDL_main
function that calls SDL_EnterAppMainCallbacks
with the callbacks that you have defined.