本文主要介绍 SDL2 库的基本使用.
一个简单的 SDL2 程序 main.c
1 | // #define SDL_MAIN_HANDLED |
编译
1 | gcc main.c -lmingw32 -lSDL2main -lSDL2 |
若去掉 -lmingw32 -lSDL2main
则需要在
#include <SDL2/SDL.h>
之前添加
#define SDL_MAIN_HANDLED
以避免找不到
WinMain
因为 SDL_MAIN_HANDLED 在 sdl_main.h 中有如下定义
1 |
|
并且
1 |
|
也就是说默认情况下没有定义 SDL_MAIN_HANDLED
的话,
#include <SDL2/SDL.h>
就会把 main 宏替换成 SDL_main,
而宏在编译链接之前替换, 所以在链接时就会发现找不到 main 函数(或说
WinMain), 而如果链接到 -lmingw32 -lSDL2main
则不存在该问题(需要放在 -lSDL2 前面),因为 -lSDL2main 提供了 main 函数.
这时候实际的 man 函数其实不是在自己定义源文件里, 而是在 libSDL2main
里.
而如果我们定义了 SDL_MAIN_HANDLED 就是要求使用我们自己的 main
函数就,不要发生宏替换,这种情况可以直接使用 -lSDL2
1 | gcc main.c -lSDL2 |
- 使用 pkg-config, 如果通过包管理器安装 sdl2, 在下载的同时一般都会附加 pkg-config 的 .pc 配置文件, 比如 MSYS2 下
1 | # 下载 ucrt64 的 SDL2 包 |
这时, 使用 pkg-config 查看包配置的输出
1 | pkg-config sdl2 --cflags --libs |
-lmingw32 -lSDL2main
和上面直接编译的一样, pkg-config
默认还附加的 -mwindows
用于启动时禁止终端弹出
于是
1 | gcc main.c `pkg-config sdl2 --cflags --libs` |
- 使用 cmake
同样的通过包管理器安装的 sdl2 还附加了 cmake 包的配置, 也是在 lib 下,
1 | find /ucrt64/lib -name "*SDL2*" |
可以看到 Cmake 的话有多种配置可供选择
直接使用默认配置的 CmakeLists.txt 如下:
1 | cmake_minimum_required(VERSION 3.10) |
通过 find_package 查找包, 然后通过 ${<包名>_LIBRARIES} 进行引用
使用 message(${SDL2_LIBRARIES})
查看 cmake 变量,
可以看到 ${SDL2_LIBRARIES}
值为
SDL2::SDL2mainSDL2::SDL2
, 默认链接到了 SDL2main
- 静态链接
通过 find /ucrt64/lib -name "*SDL2*"
可以看到 .a 文件,
说明下载的 SDL2 包是包含静态链接库的, 我们试图直接使用 -static 来编译,
发现出现很多 undefined reference to __imp
说明除了
libSDL2.a 外还需要其他依赖库才能进行静态编译, 而具体需要哪些,
我们目前无法得知.
于是尝试通过 pkg-config sdl2 --cflags --libs --static
发现可以得到所有依赖库, 即
1 | pkg-config sdl2 --cflags --libs --static |
于是静态编译指令为
1 | gcc main.c `pkg-config sdl2 --cflags --libs --static` -static |
Cmake 静态链接在 SDL 配置规则里也已经集成, 只需将 SDL2 库换成
SDL2::SDL2-static
:
1 | cmake_minimum_required(VERSION 3.10) |
如果不使用 SDL2::SDL2main
即只链接到
SDL2::SDL2-static
:
target_link_libraries(a SDL2::SDL2-static)
则需要在
#include <SDL2/SDL.h>
之前定义
#define SDL_MAIN_HANDLED
以禁止宏替换.