Wayland环境下SDL2程序无法显示窗口的问题求助
SDL2程序在Wayland环境下无法显示窗口的问题
问题描述
- 切换至Wayland环境后,SDL2编写的C程序无法创建显示窗口
- 程序已实现渲染器与事件循环,编译运行无报错
- 修改
SDL_VIDEODRIVER环境变量无效 - 经调试确认事件循环已进入,且满足Wayland要求的事件循环与缓冲区提交条件
- 系统环境:sway 1:1.8.1-5、Wayland 1.22.0-1、Linux 6.7.4.arch1-1
用户提供的代码:
#include <SDL2/SDL.h> #include <stdbool.h> #include <stdio.h> const int SCREEN_HEIGHT = 1080; const int SCREEN_WIDTH = 1920; bool init(SDL_Window *window, SDL_Renderer *renderer); void quit(SDL_Window *window, SDL_Renderer *renderer); int main(int argc, char **argv) { SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; if (!init(window, renderer)) { printf("init fail :( %s\n", SDL_GetError()); quit(window, renderer); return 1; } bool quitGame = false; while (!quitGame) { SDL_RenderClear(renderer); SDL_Rect greenSquare = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 500, 500}; SDL_RenderFillRect(renderer, &greenSquare); SDL_RenderPresent(renderer); SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: quitGame = true; break; case SDL_KEYDOWN: if (e.key.keysym.sym == SDLK_j) { printf("hi!"); } break; } } SDL_Delay(100); } return 0; } bool init(SDL_Window *window, SDL_Renderer *renderer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("sdl init fail :( %s\n", SDL_GetError()); return false; } if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) { printf("warning: linear texture filtering not enabled :("); } window = SDL_CreateWindow("test window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == NULL) { printf("window fail :( %s\n", SDL_GetError()); return false; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { printf("renderer fail :( %s\n", SDL_GetError()); return false; } SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); return true; } void quit(SDL_Window *window, SDL_Renderer *renderer) { SDL_DestroyRenderer(renderer); renderer = NULL; SDL_DestroyWindow(window); window = NULL; SDL_Quit(); printf("bye \(;-\;)"); }
问题根源与修复方案
核心问题
init函数中,SDL_Window*和SDL_Renderer*采用值传递方式传入。函数内部对window和renderer的赋值仅作用于函数内的局部变量,不会修改main函数中声明的指针变量。这导致main里的window和renderer始终为NULL——虽然SDL对空指针操作有一定容错,程序不会直接崩溃,但实际窗口从未被创建成功。
修复方式一:使用指针的指针传递参数
修改init函数的参数类型为指针的指针,让函数能够修改main中的指针变量:
#include <SDL2/SDL.h> #include <stdbool.h> #include <stdio.h> const int SCREEN_HEIGHT = 1080; const int SCREEN_WIDTH = 1920; bool init(SDL_Window **window, SDL_Renderer **renderer); void quit(SDL_Window *window, SDL_Renderer *renderer); int main(int argc, char **argv) { SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; // 传入指针的地址 if (!init(&window, &renderer)) { printf("init fail :( %s\n", SDL_GetError()); quit(window, renderer); return 1; } bool quitGame = false; while (!quitGame) { SDL_RenderClear(renderer); SDL_Rect greenSquare = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 500, 500}; SDL_RenderFillRect(renderer, &greenSquare); SDL_RenderPresent(renderer); SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: quitGame = true; break; case SDL_KEYDOWN: if (e.key.keysym.sym == SDLK_j) { printf("hi!"); } break; } } SDL_Delay(100); } quit(window, renderer); return 0; } // 修改参数为指针的指针 bool init(SDL_Window **window, SDL_Renderer **renderer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("sdl init fail :( %s\n", SDL_GetError()); return false; } if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) { printf("warning: linear texture filtering not enabled :("); } // 通过指针的指针修改外部变量 *window = SDL_CreateWindow("test window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (*window == NULL) { printf("window fail :( %s\n", SDL_GetError()); return false; } *renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED); if (*renderer == NULL) { printf("renderer fail :( %s\n", SDL_GetError()); return false; } SDL_SetRenderDrawColor(*renderer, 0x00, 0xFF, 0x00, 0xFF); return true; } void quit(SDL_Window *window, SDL_Renderer *renderer) { if (renderer != NULL) { SDL_DestroyRenderer(renderer); } if (window != NULL) { SDL_DestroyWindow(window); } SDL_Quit(); printf("bye \(;-\;)"); }
修复方式二:返回包含资源的结构体
定义一个结构体封装窗口和渲染器,让init函数返回该结构体,代码结构更清晰:
#include <SDL2/SDL.h> #include <stdbool.h> #include <stdio.h> const int SCREEN_HEIGHT = 1080; const int SCREEN_WIDTH = 1920; typedef struct { SDL_Window* window; SDL_Renderer* renderer; bool initialized; } AppContext; AppContext init(); void quit(AppContext ctx); int main(int argc, char **argv) { AppContext ctx = init(); if (!ctx.initialized) { printf("init fail :( %s\n", SDL_GetError()); quit(ctx); return 1; } bool quitGame = false; while (!quitGame) { SDL_RenderClear(ctx.renderer); SDL_Rect greenSquare = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 500, 500}; SDL_RenderFillRect(ctx.renderer, &greenSquare); SDL_RenderPresent(ctx.renderer); SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: quitGame = true; break; case SDL_KEYDOWN: if (e.key.keysym.sym == SDLK_j) { printf("hi!"); } break; } } SDL_Delay(100); } quit(ctx); return 0; } AppContext init() { AppContext ctx = {NULL, NULL, false}; if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("sdl init fail :( %s\n", SDL_GetError()); return ctx; } if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) { printf("warning: linear texture filtering not enabled :("); } ctx.window = SDL_CreateWindow("test window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (ctx.window == NULL) { printf("window fail :( %s\n", SDL_GetError()); return ctx; } ctx.renderer = SDL_CreateRenderer(ctx.window, -1, SDL_RENDERER_ACCELERATED); if (ctx.renderer == NULL) { printf("renderer fail :( %s\n", SDL_GetError()); return ctx; } SDL_SetRenderDrawColor(ctx.renderer, 0x00, 0xFF, 0x00, 0xFF); ctx.initialized = true; return ctx; } void quit(AppContext ctx) { if (ctx.renderer != NULL) { SDL_DestroyRenderer(ctx.renderer); } if (ctx.window != NULL) { SDL_DestroyWindow(ctx.window); } SDL_Quit(); printf("bye \(;-\;)"); }
额外优化
- 在
quit函数中增加空指针判断,避免对NULL资源执行销毁操作 main函数结束前主动调用quit函数,确保资源被正确释放
内容的提问来源于stack exchange,提问作者Llamalectric
相关产品推荐
相关产品推荐

