SDL3 入门(1):Hello, SDL3!
在本系列中我们使用 Windows Terminal + Powershell 组合作为我们在 Windows 系统下的终端工具,Windows 11 自带该环境。你也可以使用任意自己喜欢的终端环境代替,或使用鼠标执行等价的操作。
源码准备
我们使用 git 管理我们的项目,所以首先我们创建一个名为 "hello_sdl3" 的目录并且使用 git 进行初始化,这组命令实际上是各平台通用的:
mkdir hello_sdl3
cd ./hello_sdl3
git init
使用 git submodule 机制引入 SDL3 的源代码,源码地址: https://github.com/libsdl-org/SDL.git
git submodule add https://github.com/libsdl-org/SDL.git ./third_party/SDL3
如果不使用 git 可以手工下载源码到对应的目录,不影响后续使用。
接下来在项目文件夹根目录下创建源码文件和 CMakeLists.txt 文件:
hello_window.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
int main(int argc, char* argv[])
{
SDL_Log("Hello, SDL3!");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(hello_sdl3)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/third_party/SDL3" EXCLUDE_FROM_ALL)
link_libraries(SDL3::SDL3)
add_executable(hello_window hello_window.cpp)
编译运行
创建并切换当前目录到 build 文件夹
mkdir build
cd ./build
执行 cmake 命令初始化项目配置,cmake 会自动扫描系统安装的开发环境,在 Windows 系统下一般是 VisualStudio(简称 VS)开发环境:
cmake ..
一切顺利的话已经可以看到 build 文件夹下生成的 VisualStudio 工程文件,接下来可以使用 VS 打开 sln 文件执行编译调试等工作,也可以继续使用 cmake 命令编译。

cmake 命令编译项目:
cmake --build .
如果编译成功可以在 build/Debug 文件夹下看到 hello_window.exe 可执行文件,如果使用 clang 编译则直接在 build 文件夹下。命令行执行:

呃,没输出任何字符,有点不合预期
这里是因为我们以动态链接库(DLL)的方式使用 SDL3,而 SDL3.dll 并没有生成到 build/Debug 文件夹下,hello_window.exe 可执行程序找不到需要的 DLL 所以无法启动。
解决方法是使用 CMake 的 add_custom_command 方法自定义文件拷贝指令,在 CMakeLists.txt 中增加如下内容:
add_custom_command(TARGET hello_window POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:SDL3::SDL3>
$<TARGET_FILE_DIR:hello_window>
)
重新编译执行,输出如下:

搞定!
至此,说明我们已经解决基本的工程设置、动态库依赖等一系列问题,接下来可以继续编写更复杂的程序了。
注意事项
注意观察 hello_window.cpp 文件的源码,如果 IDE 比较智能的话可以看到 "main" 这个单词不是正常的表示函数名的颜色,比如在我这里它显示的是蓝色,这表示 "main" 是一个宏。
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
int main(int argc, char* argv[])
...
玄机在 SDL_main.h 中:
#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) || defined(SDL_MAIN_USE_CALLBACKS)
#define main SDL_main
#endif
"main" 被宏定义修改成了 "SDL_main",因此 main 函数的声明必须写成带参数的完整形式,不能使用如下的无参写法:
int main()
{
...
}
否则会在链接时报 "无法解析的外部符号" 错误,因为无法解析的符号是 "SDL_main" 所以如果不熟悉 SDL 的话即使是有经验的 C++ 程序员(比如我)也颇为挠头(万恶的宏)。去掉 #include <SDL3/SDL_main.h> 这一行或者使用完整的 main 函数声明都可以解决问题。
不过 SDL_main.h 头文件还有其他用处,在 Windows 下如果希望将程序编译成窗口程序(启动后不带控制台)则必须包含这个头文件,同时在 CMakeLists.txt 中增加如下内容:
set_property(TARGET hello_window PROPERTY WIN32_EXECUTABLE TRUE)
不过这样在调试过程就看不到日志了,需要做一些额外的处理接管日志输出,所以在调试阶段建议继续使用控制台类型编译可执行程序。
SDL3 入门(1):Hello, SDL3!的更多相关文章
- C语言的本质(15)——C语言的函数接口入门
C语言的本质(15)--C语言的函数接口 函数的调用者和其实现者之间存在一个协议,在调用函数之前,调用者要为实现者提供某些条件,在函数返回时,实现者完成调用者需要的功能. 函数接口通过函数名,参数和返 ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
随机推荐
- Dubbo 3.0 前瞻系列 | 2020双11,Dubbo3.0 在考拉的超大规模实践
很多开发者一直以来好奇:阿里自己有没有在用Dubbo,会不会用Dubbo?在刚刚结束的双11,我们了解到阿里云今年提出了"三位一体"的理念,即将"自研技术".& ...
- 一文了解阿里一站式图计算平台GraphScope
简介: 随着大数据的爆发,图数据的应用规模不断增长,现有的图计算系统仍然存在一定的局限.阿里巴巴拥有全球最大的商品知识图谱,在丰富的图场景和真实应用的驱动下,阿里巴巴达摩院智能计算实验室研发并开源了全 ...
- 网易云音乐音视频算法的 Serverless 探索之路
简介: 基于音视频算法服务化的经验,网易云音乐曲库团队与音视频算法团队一起协作,一起共建了网易云音乐音视频算法处理平台,为整个云音乐提供统一的音视频算法处理平台.本文将分享我们如何通过 Server ...
- 2019-10-31-VisualStudio-断点调试详解
title author date CreateTime categories VisualStudio 断点调试详解 lindexi 2019-10-31 8:56:7 +0800 2019-06- ...
- Pod进阶篇-Pod生命周期和健康探测以及startupProbe(6)
一.Pod容器探测和钩子 1.1 容器钩子:postStart和preStop postStart:容器创建成功后,运行前的任务,用于资源部署.环境准备等. preStop:在容器被终止前的任务,用于 ...
- (数据科学学习手札160)使用miniforge代替miniconda
本文已收录至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,conda作为Python数据科学领域 ...
- GIS中XYZ瓦片的加载流程解析与实现
1. 什么是XYZ瓦片 XYZ瓦片是一种在线地图数据格式,常见的地图底图如Google.OpenStreetMap 等互联网的瓦片地图服务,都是XYZ瓦片,严格来说是ZXY规范的地图瓦片 ZXY规范的 ...
- netcore依赖注入通过反射简化
aspnetcore里面用到许多的service,好多业务代码都要通过Service.AddScoped.Singleton.Transient等注入进去,类太多了写起来和管理起来都很麻烦,所以借鉴了 ...
- Codeforces Round 932 (Div. 2) ABCD
A. Entertainment in MAC 题意:给定字符串 \(S\),有两种操作,每次操作其中之一: 把 \(S\) 变为 \(S\) 的翻转 \(T\). 把 \(S\) 变为 \(S + ...
- JUC并发编程学习笔记(二)Lock锁(重点)
Lock锁(重点) 传统的synchronized 传统的解决多线程并发导致的一些问题我们会使用synchronized关键字来解决,synchronized的本质就是队列.锁. Lock的实现类有: ...