SDL2渲染到纹理示例无窗口显示:版本变化还是Mac兼容问题?
问题描述
学习SDL2渲染到纹理模式时,我从Stack Overflow找到一份示例代码,编译执行无报错,程序会按设定运行8秒,但始终没有窗口显示。将窗口位置改为SDL_WINDOWPOS_UNDEFINED也无效果。
想问:是SDL2十年间的更新导致示例失效?还是Mac系统存在特殊兼容问题?
我的环境:搭载苹果硅芯片的Mac OS 14.2.1,SDL2为近期下载版本,原代码如下:
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <SDL2/SDL.h> // Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2 void putPixel(SDL_Renderer *renderer, int x, int y) { SDL_SetRenderDrawColor(renderer, 255,255,255,255); SDL_RenderDrawPoint(renderer, x, y); } int main(int argc, char* argv[]) { int width = 640; int height = 480; SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0); if (window == NULL) { return -1; } SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); if (renderer == NULL) { return -2; } SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND); /* Create texture for display */ SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); SDL_SetRenderTarget(renderer, display); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); for(int x=0;x<8;x++) { SDL_SetRenderTarget(renderer, display); for(int y=0;y<10;y++) { putPixel(renderer,40+x*10,50+y); } SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, display, NULL, NULL); SDL_RenderPresent(renderer); sleep(1); } SDL_Quit(); return 0; }
问题原因与解决办法
核心问题
- 窗口未设置显示标志:原代码创建窗口时未传入
SDL_WINDOW_SHOWN,Mac系统下窗口默认处于隐藏状态。 - 主线程被阻塞未处理事件:使用
sleep(1)会完全阻塞主线程,SDL的窗口管理器需要主线程响应事件才能正确绘制窗口。 - Apple Silicon架构路径适配:通过brew安装的SDL2在苹果硅Mac上的路径是
/opt/homebrew,而非原代码注释的/usr/local,原编译命令可能链接到错误架构的库。
修改后的可运行代码
#include <stdlib.h> #include <stdio.h> #include <SDL2/SDL.h> // Apple Silicon编译命令: gcc test.c -I/opt/homebrew/include/SDL2 -L/opt/homebrew/lib -lSDL2 void putPixel(SDL_Renderer *renderer, int x, int y) { SDL_SetRenderDrawColor(renderer, 255,255,255,255); SDL_RenderDrawPoint(renderer, x, y); } int main(int argc, char* argv[]) { // 显式初始化SDL视频子系统,新版本SDL必须调用 if (SDL_Init(SDL_INIT_VIDEO) != 0) { fprintf(stderr, "SDL初始化失败: %s\n", SDL_GetError()); return -1; } int width = 640; int height = 480; // 添加SDL_WINDOW_SHOWN标志,确保窗口创建后直接显示 SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); if (window == NULL) { fprintf(stderr, "创建窗口失败: %s\n", SDL_GetError()); SDL_Quit(); return -1; } SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); if (renderer == NULL) { fprintf(stderr, "创建渲染器失败: %s\n", SDL_GetError()); SDL_DestroyWindow(window); SDL_Quit(); return -2; } SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND); /* 创建目标纹理 */ SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); if (display == NULL) { fprintf(stderr, "创建纹理失败: %s\n", SDL_GetError()); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return -3; } SDL_SetRenderTarget(renderer, display); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); for(int x=0;x<8;x++) { SDL_SetRenderTarget(renderer, display); for(int y=0;y<10;y++) { putPixel(renderer,40+x*10,50+y); } SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, display, NULL, NULL); SDL_RenderPresent(renderer); // 用SDL_Delay配合事件循环替代sleep,避免主线程完全阻塞 SDL_Event event; Uint32 start = SDL_GetTicks(); while (SDL_GetTicks() - start < 1000) { while (SDL_PollEvent(&event)) { // 处理窗口关闭事件 if (event.type == SDL_QUIT) { SDL_DestroyTexture(display); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; } } } } // 释放资源 SDL_DestroyTexture(display); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
关键修改说明
- 显式调用
SDL_Init(SDL_INIT_VIDEO):新版本SDL不再隐式初始化子系统,必须显式声明初始化模块。 - 添加
SDL_WINDOW_SHOWN窗口标志:强制窗口创建后立即显示,解决Mac下窗口隐藏的问题。 - 替换
sleep(1)为事件循环+SDL_Delay:让主线程在等待期间处理窗口事件,保证窗口能正常渲染。 - 修正Apple Silicon编译路径:适配brew安装的SDL2在苹果硅Mac上的默认路径。
- 添加错误日志输出:方便排查初始化失败的具体原因。
内容的提问来源于stack exchange,提问作者Joymaker
相关产品推荐
相关产品推荐

