在本系列中我们使用 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!的更多相关文章

  1. C语言的本质(15)——C语言的函数接口入门

    C语言的本质(15)--C语言的函数接口 函数的调用者和其实现者之间存在一个协议,在调用函数之前,调用者要为实现者提供某些条件,在函数返回时,实现者完成调用者需要的功能. 函数接口通过函数名,参数和返 ...

  2. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  3. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  4. Oracle分析函数入门

    一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...

  5. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  6. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  7. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  8. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  9. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

  10. wepack+sass+vue 入门教程(一)

    一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...

随机推荐

  1. MySQL 深潜 - MDL 锁的实现与获取机制

    简介:本文将介绍在 MDL 系统中常用的数据结构及含义,然后从实现角度讨论 MDL 的获取机制与死锁检测,最后分享在实践中如何监控 MDL 状态. ​ 作者 | 泊歌 来源 | 阿里技术公众号 一 背 ...

  2. WPF 已知问题 资源字典树引用与资源寻找的坑

    大家都知道,在 WPF 里面,可以让资源字典合并其他资源字典,从而定义出资源字典引用树.然而在资源字典引用树里面,如果没有理清关系,将可以作出一个超级复杂的引用关系网.如果在性能优化中,将网断开部分, ...

  3. 使用sqlcmd命令行执行.sql文件

    用微软自带的sqlcmd命令行工具,可以执行导入.以SQL Server 2016版本为例: 第一步:Win+R 键入:cmd 命令,开启命令行工具: 第二步:键入:sqlcmd -S . -U sa ...

  4. 3.Exporter概述

    一.Exporter概述 所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter.而Exporter的一个实例称为target,如下所示,Prometheus通过轮询的方 ...

  5. 使用Binlog日志恢复误删的MySQL数据实战

    前言 "删库跑路"是程序员经常谈起的话题,今天,我就要教大家如何删!库!跑!路! 开个玩笑,今天文章的主题是如何使用Mysql内置的Binlog日志对误删的数据进行恢复,读完本文, ...

  6. 二:大数据架构回顾-Kappa架构

    Kappa 架构是由 LinkedIn 的前首席工程师杰伊·克雷普斯(Jay Kreps)提出的一种架构思想.克雷普斯是几个著名开源项目(包括 Apache Kafka 和 Apache Samza ...

  7. kali 设置 Java 版本,并更换为 1.8 版本

    kali 设置 Java 版本,并更换为 1.8 版本 1.安装 JDK 1.下载java 1.8 :https://repo.huaweicloud.com/java/jdk/8u202-b08/j ...

  8. su与sudo用法详解

    su与sudo用法详解 目录 su与sudo用法详解 1. su和sudo详解:切换用户身份 1.1 shell登录类型和环境配置文件 1.2 su进行身份切换 1.3 sudo命令详解 1.3.1 ...

  9. Js中valueOf和toString区别和使用

    对于number.string.Boolean.object.symbol数据类型调用valueOf方法,得到的都是数据本身(null.undefined两种类型上的原型链上没有valueOf方法) ...

  10. js原生小知识

    new Array(3).fill(0) 就会生成3个元素为0的数组