#sdl #graphics #windowing

sys sdl2-sys

为Rust提供的原始SDL2绑定,由rust-sdl2内部使用

58次发布

0.37.0 2024年6月13日
0.36.0 2023年11月22日
0.35.2 2022年2月6日
0.35.1 2021年10月25日
0.0.33 2015年3月26日

#176 in 游戏开发

Download history 10165/week @ 2024-05-04 10122/week @ 2024-05-11 10401/week @ 2024-05-18 10115/week @ 2024-05-25 10403/week @ 2024-06-01 7214/week @ 2024-06-08 9054/week @ 2024-06-15 8211/week @ 2024-06-22 5394/week @ 2024-06-29 4330/week @ 2024-07-06 7814/week @ 2024-07-13 7657/week @ 2024-07-20 7584/week @ 2024-07-27 6626/week @ 2024-08-03 11892/week @ 2024-08-10 6932/week @ 2024-08-17

34,181 每月下载量
用于317 个Crate中(直接使用19个)

MIT AND Zlib

15MB
325K SLoC

C 230K SLoC // 0.1% comments Rust 31K SLoC // 0.0% comments Objective-C 14K SLoC // 0.1% comments Visual Studio Project 11K SLoC Shell 9K SLoC // 0.2% comments C++ 9K SLoC // 0.2% comments M4 9K SLoC // 0.2% comments Java 8K SLoC // 0.2% comments Perl 2K SLoC // 0.1% comments GNU Style Assembly 661 SLoC // 0.2% comments Visual Studio Solution 547 SLoC JavaScript 286 SLoC // 0.4% comments Automake 168 SLoC // 0.0% comments Metal Shading Language 100 SLoC Batch 92 SLoC Python 91 SLoC // 0.1% comments HICAD 36 SLoC Prolog 15 SLoC Xcode Config 8 SLoC // 0.6% comments Snakemake 2 SLoC // 0.9% comments

包含(自动工具混淆代码,1MB)SDL/configure,(模糊autoconf代码,190KB)SDL/configure.ac,(自动工具混淆代码,175KB)SDL/test/configure,(自动工具混淆代码,130KB)SDL/visualtest/configure,(JAR文件,55KB)gradle-wrapper.jar,(模糊autoconf代码,7KB)SDL/src/hidapi/configure.ac 等更多内容。

Rust-SDL2 构建状态 crates.io徽章

SDL2在Rust中的绑定

0.37.0版本变更日志

概述

Rust-SDL2是一个库,用于从Rust调用新的SDL2.0库。通过将低级别的C组件包装在Rust代码中来使它们更符合规范,并抽象掉不适当的手动内存管理。

Rust-SDL2使用MIT许可,但SDL2本身是在zlib许可下。

可用的Rust功能

  • gfx 用于链接到SDL2_gfx并访问gfx功能
  • image 用于链接到SDL2_image并访问图像读取和写入功能
  • mixer 用于链接到SDL2_mixer并访问声音混合功能
  • ttf 用于链接到SDL2_ttf并访问各种字体功能
  • raw-window-handle 用于启用crate raw-window-handle,这对于与其他后端互操作很有用。
  • unsafe-textures 用于不在 Texture 结构中保持生命周期。纹理只在程序退出时释放,或者可以通过 unsafe 手动释放。
  • 使用 use-bindgen 来自定义绑定,而不是使用从 Linux 环境中创建的预生成的 sdl_bindings。它为您生成自定义的 SDL2 绑定,针对您的发行版进行优化。对于特定的窗口相关场景非常有用。
  • 使用 use-vcpkg 从 vcpkg 中获取 SDL2,而不是在您的系统中查找。
  • 使用 use-pkgconfig 使用 pkg-config 检测您的库在系统中的位置。主要用于 Unix 系统上的静态链接。
  • 使用 static-link 将 SDL2 静态链接,而不是动态链接。
  • 使用 use_mac_framework 在 macOS 上仅从 Framework 中使用 SDL2
  • 使用 use_ios_framework 在 iOS 上仅从 Framework 中使用 SDL2
  • bundled,它将 SDL 仓库拖入并从源代码进行编译。更多信息见下文。

文档

在此处阅读文档.

要求

Rust

我们目前针对 Rust 的最新稳定版进行目标编译。

SDL2.0 开发库

建议使用 SDL2 >= 2.0.26 的绑定;低于 2.0.26 的版本,您可能会遇到链接时错误,因为这里使用了一些函数,但它们在 SDL2 中未定义。如果您在使用 LTS 机器(例如 Ubuntu)时遇到此问题,我们强烈建议您使用“捆绑”功能,该功能将为您的项目编译最新的稳定版 SDL2。

“捆绑”功能

从 0.31 版本开始,此 crate 支持一个名为“捆绑”的功能,它从源代码编译 SDL2 并自动链接。虽然这应该适用于任何架构,但您必须有一个 C 编译器(如 gccclang 或 MS 自家的编译器)才能正确使用此功能。

默认情况下,macOS 和 Linux 只从系统目录(如 /usr/lib)加载库。如果您希望与您的可执行文件一起分发新构建的 libSDL2.so/libSDL2.dylib,则需要将 rpath 添加到您的可执行文件中。将以下行添加到 build.rs 脚本

#[cfg(target_os="macos")]
println!("cargo:rustc-link-arg=-Wl,-rpath,@loader_path");

#[cfg(target_os="linux")]
println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN");

**这仅适用于 SDL2,不适用于 SDL2_image、SDL2_mixer、SDL2_ttf、SDL2_gfx**

Linux

通过您喜欢的包管理工具安装这些库,或通过 http://www.libsdl.org/

Ubuntu 示例

sudo apt-get install libsdl2-dev

Fedora 示例

sudo dnf install SDL2-devel

Arch 示例
(Arch 没有分开的常规和开发包,所有内容都在一起.)

sudo pacman -S sdl2

您可能还需要一个 C 编译器(gcc)。

Linux 中的静态链接

您可以选择使用 static-link 功能将 SDL2 静态链接而不是动态链接。在 Linux 上,您还需要执行以下操作之一

  • 使用 bundled 功能
  • 使用功能 use-pkgconfig,以便 rustc 知道在哪里查找您的 SDL2 库及其静态链接的依赖项。这是必需的,因为从您的系统中静态链接 SDL2 没有内置的方法来查找所需资源
  • 使用 vcpkg 安装开发库。使用 vcpkg 在 Linux 和其他操作系统上生成静态二进制文件的说明 在此处

macOS

Homebrew

在 macOS 上,建议通过 homebrew 安装这些库。

brew install sdl2

在 Homebrew 的最新版本中,安装的库通常链接到 $(brew --prefix)/lib。如果您正在运行较旧版本,SDL 的符号链接可能位于 /usr/local/lib

为了使通过Homebrew安装的库的链接更容易,请根据您各自的shell执行以下操作。

根据您是否使用ZSH或Bash,将以下行添加到您的 ~/.zshenv~/.bash_profile

export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"

MacPorts

您还可以通过 macports 获取sdl2。

sudo port install libsdl2

如果尚未存在,请将以下内容添加到您的 ~/.bash_profile

export LIBRARY_PATH="$LIBRARY_PATH:/opt/local/lib/"

如果您在Homebrew或MacPorts上遇到问题,请参阅此处

如果您正在使用SDL2框架

您可以从https://www.libsdl.org/download-2.0.php 下载并安装SDL2 Mac OS X框架。

要使 sdl2 crate与SDL2框架链接,您需要启用 use_mac_framework 功能。要使用此功能构建和测试 sdl2 crate,请使用

cargo test --features use_mac_framework

要使用此功能依赖 sdl2 crate,请将以下内容放入您的项目的 Cargo.toml 文件中

[dependencies.sdl2]
features = ["use_mac_framework"]
version = ...  # Whichever version you are using

或者,您可以通过在 Cargo.toml 文件中放置以下内容来在您的包中重新导出此功能

[features]
default = []
use_sdl2_mac_framework = ["sdl2/use_mac_framework"]

对于iOS,您可以遵循相同的过程使用 use_ios_framework 功能。但是,iOS框架的官方构建不可用,因此您必须自己编译SDL2.framework。

使用iOS框架还要求将 'Frameworks' 目录添加到您的rpath中,以便动态链接器可以在您的应用程序包内找到SDL2.framework。这可以通过在 build.rs 中添加以下内容来完成

#[cfg(target_os="ios")]
println!("cargo:rustc-link-arg=-Wl,-rpath,@loader_path/Frameworks");

使用vcpkg在macOS上静态链接

使用vcpkg在macOS和其他操作系统上生成静态二进制文件的说明在此

Windows (MSVC)

  1. http://www.libsdl.org/ 下载MSVC开发库(SDL2-devel-2.0.x-VC.zip)。

  2. 将 SDL2-devel-2.0.x-VC.zip 解压缩到您选择的文件夹中(之后您可以删除它)。

  3. 将以下lib文件从

    SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

    复制到(对于Rust 1.6及以上版本)

    C:\Program Files\Rust\lib\rustlib\x86_64-pc-windows-msvc\lib

    或(对于Rust版本1.5及以下)

    C:\Program Files\Rust\bin\rustlib\x86_64-pc-windows-msvc\lib

    或复制到您选择的库文件夹,并确保您有一个名为

    LIB = C:\your\rust\library\folder

    Rustup用户,此文件夹位于

    C:\Users\{Your Username}\.rustup\toolchains\{current toolchain}\lib\rustlib\{current toolchain}\lib

其中当前工具链可能是 stable-x86_64-pc-windows-msvc

  1. 将 SDL2.dll 从

    SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

    复制到您的 cargo 项目中,紧挨着您的 Cargo.toml。

  2. 当您发布您的游戏时,请确保将 SDL2.dll 复制到与您的编译 exe 相同的目录中,否则游戏将无法启动。

使用MSVC进行静态链接

http://libsdl.org/ 提供的MSVC开发库不包括静态库。这意味着,如果您想使用 static-link 功能与 windows-msvc 工具链一起使用,您必须执行以下操作之一

  • 自己构建SDL2静态库并将其复制到工具链的 lib 目录中;或者
  • 同时启用 bundled 功能,这将为您构建一个静态库;或者
  • 使用下面描述的vcpkg中的静态SDL2库。

Windows (MinGW)

  1. http://www.libsdl.org/ 下载mingw开发库(SDL2-devel-2.0.x-mingw.tar.gz)。

  2. 解压缩到您选择的文件夹中(之后您可以删除它)。

  3. 将以下lib文件从

    SDL2-devel-2.0.x-mingw\SDL2-2.0.x\x86_64-w64-mingw32\lib

    复制到(对于Rust 1.6及以上版本)

    C:\Program Files\Rust\lib\rustlib\x86_64-pc-windows-gnu\lib

    或(对于Rust版本1.5及以下)

    C:\Program Files\Rust\bin\rustlib\x86_64-pc-windows-gnu\lib

    或复制到您选择的库文件夹,并确保您有一个名为

    LIBRARY_PATH = C:\your\rust\library\folder

    Rustup用户,此文件夹位于

    C:\Users\{Your Username}\.rustup\toolchains\{current toolchain}\lib\rustlib\{current toolchain}\lib

其中当前工具链可能是 stable-x86_64-pc-windows-gnu

  1. 将 SDL2.dll 从

    SDL2-devel-2.0.x-mingw\SDL2-2.0.x\x86_64-w64-mingw32\bin

    复制到您的 cargo 项目中,紧挨着您的 Cargo.toml。

  2. 当您发布您的游戏时,请确保将 SDL2.dll 复制到与您的编译 exe 相同的目录中,否则游戏将无法启动。

使用MinGW进行静态链接

如果您想使用windows-gnu工具链的static-link功能,则需要以下库

libimm32.a
libversion.a
libdinput8.a
libdxguid.a

这些文件当前未包含在windows-gnu工具链中,但可以从此处下载。对于x86_64工具链,您需要x86_64-win32-seh包,对于i686则需要i686-win32-dwarf包。

您可以在mingw64/x86_64-w64-mingw32/lib/(对于x86_64)或mingw32/i686-w64-mingw32/lib/(对于i686)下找到上述库。将它们复制到您的工具链的lib目录(与您复制SDL .a文件的目录相同)。

带构建脚本的Windows

  1. http://www.libsdl.org/(SDL2-devel-2.0.x-mingw.tar.gz & SDL2-devel-2.0.x-VC.zip)下载mingw和msvc开发库。
  2. 解压缩到您选择的文件夹(之后可以删除)。
  3. 在Cargo.toml相同的文件夹中创建以下文件夹结构
gnu-mingw\dll\32
gnu-mingw\dll\64
gnu-mingw\lib\32
gnu-mingw\lib\64
msvc\dll\32
msvc\dll\64
msvc\lib\32
msvc\lib\64
  1. 将源存档中的lib和dll文件复制到步骤3中创建的目录,如下所示
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\i686-w64-mingw32\bin 		-> 	gnu-mingw\dll\32
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\x86_64-w64-mingw32\bin 	-> 	gnu-mingw\dll\64
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\i686-w64-mingw32\lib 		-> 	gnu-mingw\lib\32
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\x86_64-w64-mingw32\lib 	-> 	gnu-mingw\lib\64
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x86\*.dll	 		-> 	msvc\dll\32
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x64\*.dll 			-> 	msvc\dll\64
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x86\*.lib	 		-> 	msvc\lib\32
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x64\*.lib	 		-> 	msvc\lib\64
  1. 如果您还没有构建脚本,请在Cargo.toml中创建一个构建脚本,并将其放入以下位置

build = "build.rs"

  1. 在Cargo.toml相同的目录中创建一个名为build.rs的文件(如果您还没有构建脚本),并将以下内容粘贴进去
use std::env;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("pc-windows") {
        let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        let mut lib_dir = manifest_dir.clone();
        let mut dll_dir = manifest_dir.clone();
        if target.contains("msvc") {
            lib_dir.push("msvc");
            dll_dir.push("msvc");
        }
        else {
            lib_dir.push("gnu-mingw");
            dll_dir.push("gnu-mingw");
        }
        lib_dir.push("lib");
        dll_dir.push("dll");
        if target.contains("x86_64") {
            lib_dir.push("64");
            dll_dir.push("64");
        }
        else {
            lib_dir.push("32");
            dll_dir.push("32");
        }
        println!("cargo:rustc-link-search=all={}", lib_dir.display());
        for entry in std::fs::read_dir(dll_dir).expect("Can't read DLL dir")  {
            let entry_path = entry.expect("Invalid fs entry").path();
            let file_name_result = entry_path.file_name();
            let mut new_file_path = manifest_dir.clone();
            if let Some(file_name) = file_name_result {
                let file_name = file_name.to_str().unwrap();
                if file_name.ends_with(".dll") {
                    new_file_path.push(file_name);
                    std::fs::copy(&entry_path, new_file_path.as_path()).expect("Can't copy from DLL dir");
                }
            }
        }
    }
}
  1. 在构建时,构建脚本将所需的DLL复制到与Cargo.toml相同的目录,但是您可能不希望将这些DLL提交到任何Git仓库中,因此请向您的.gitignore文件中添加以下行

/*.dll

  1. 当您发布游戏时,请确保将相应的SDL2.dll复制到与编译的exe文件相同的目录中,否则游戏无法启动。

现在,您的项目应该可以在任何Windows计算机上构建和运行了!

使用MSVC的Windows

  1. 安装MS构建工具vcpkg
  2. 安装所需的SDL2库:vcpkg.exe install sdl2-ttf:x64-windows sdl2:x64-windows
  3. 打开x64原生工具提示(VS 2019的x64 Native Tools Command Prompt)
  4. 设置环境变量
SET PATH=%PATH%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\bin
SET INCLUDE=%INCLUDE%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\include
SET LIB=%LIB%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\lib
  1. cargobuild

使用vcpkg的Windows、Linux和macOS

获取开发库的另一种方法是使用vcpkg。要设置一个项目,在Windows(MSVC)、Linux或macOS上构建静态二进制文件,可以按照以下方式构建

cargo install cargo-vcpkg
cargo vcpkg build
cargo build

将以下内容添加到您的Cargo.toml

[dependencies.sdl2]
version = "0.37"
default-features = false
features = ["ttf","image","gfx","mixer","static-link","use-vcpkg"]

[package.metadata.vcpkg]
dependencies = ["sdl2", "sdl2-image[libjpeg-turbo,tiff,libwebp]", "sdl2-ttf", "sdl2-gfx", "sdl2-mixer"]
git = "https://github.com/microsoft/vcpkg"
rev = "2024.05.24" # release 2024.05.24 # to check for a new one, check https://github.com/microsoft/vcpkg/releases

[package.metadata.vcpkg.target]
x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md" }

关于cargo vcpkg工具的更多信息,请参阅此处

安装

如果您正在使用cargo来管理项目,您可以通过Crates.io下载

    [dependencies]
    sdl2 = "0.37"

或者,从GitHub拉取以获取最新版本的master

    [dependencies.sdl2]
    git = "https://github.com/rust-sdl2/rust-sdl2"

否则,克隆此仓库并运行cargo

cargo build

您可以通过添加以下内容来启用诸如ttf、image、gfx和mixer等特性

    [dependencies.sdl2]
    version = "0.37"
    default-features = false
    features = ["ttf","image","gfx","mixer"]

这些特性需要它们各自的库,可以在以下位置找到:(安装过程与SDL2相同)

那么sdl2_net呢?

截至目前,与像 serdebincode 这样的crate相比,sdl2_net没有意义。我们强烈推荐使用这些crate来开发与UDP或TCP相关的内容(连同futures或标准库中的TCP/UDP)。

如果您仍然想要sdl2_net的实现,您可以尝试通过Pull Request将它在repo中添加为一个功能。可以在这里找到这个绑定的一个相对过时的版本:这里

演示

我们包含了一些简单的示例项目

cargo run --example demo

您可以在 examples/ 文件夹中看到完整的列表。一些示例需要一些功能,您可以通过以下方式启用它们

cargo run --example gfx-demo --features "gfx"

将 "gfx" 替换为您想要示例所需的特征。

关于 unsafe_textures 特征

sdl2::render 模块中,Texture 默认有生命周期,以防止它比其父 TextureCreator 活得更久。这些生命周期有时在Rust中很难处理,因此您可以启用 unsafe_textures 特征。

这将移除 Texture 的生命周期,但代价是可选的手动内存管理。如果您想要手动销毁使用的 Texture,可以调用您的 Texturedestroy 方法,但请注意 不应 在任何父级(CanvasTextureCreator)都还活着的情况下调用它。如果您不调用此方法,内存将在最后一个 Canvas 或最后一个 TextureCreator 被释放时自动释放。

关于这个特征没有在线文档,但是您可以通过在Cargo.toml中启用该特征,运行 cargo doc 并通过浏览器访问 target/doc/sdl2/index.html 来在自己的项目中构建它。

使用bindgen生成sdl2-sys

为此crate生成的sdl2-sys非常通用,可以在许多平台上使用,限制很少。然而,您有时可能会在使用SDL2的平台特定功能时遇到麻烦,例如窗口管理器类别。

"use-bindgen" 特征允许您通过根据目标生成适当的绑定来避免这种限制。它将基于 pkg-config 输出的头文件(如果您启用了 "use-pkg-config" 特征)生成绑定。如果没有pkg-config或禁用了该特征,它将尝试在crate的 SDL-2.0.8/include 中获取头文件。

如果您有自己想使用的头文件(使用beta版本、旧版本等),您可以设置环境变量 "SDL2_INCLUDE_PATH",这些头文件将被bindgen使用。

使用sdl2-sys提供SDL2头文件/库

如果您正在为需要SDL2的库创建一个 *-*-sys crate,您可以使用 sdl2-sys 来提供编译后的库和SDL2的头文件。

按照以下步骤获取头目录。在你的 crate 的 Cargo.toml 文件中,将 sdl2-sys 添加为依赖项(不是构建依赖项)。然后,Cargo 将为你提供的构建脚本提供一个环境变量 DEP_SDL2_INCLUDE,其中包含 SDL2 的包含目录。如果有多个目录,它们将使用 : 作为分隔符组合。将这些目录传递给构建 C/C++ 的工具。

一切链接完成之后,所有 C、C++ 和 Rust 代码都将使用单个 SDL2 的副本(由 sdl2-sys 提供)。

更多讨论请见相应的 问题

OpenGL

使用 OpenGL 有两种方式

  • 作为 sdl2::render 的后端,sdl2 会为你完成所有工作。它是 Linux 设备的默认选择。
  • 手动使用,仅将 sdl2 作为窗口(类似于 glutinwinit crate)的“外壳”,并仍然使用 sdl2 的摇杆、事件、音频、文本输入等能力。

如果你想使用 OpenGL,还需要 gl-rs 包。如果你使用 cargo,只需将这些行添加到你的 Cargo.toml 文件中

    [dependencies.gl]
    git = "https://github.com/bjz/gl-rs"

使用 sdl2 有两种方式使用 OpenGL

  • 使用画布和 sdl2::render 使用 OpenGL
  • 直接在窗口“外壳”上使用 OpenGL,并使用手动 OpenGL 调用来渲染内容

使用 sdl2::render

首先,从 SDL 中找到 OpenGL 驱动

fn find_sdl_gl_driver() -> Option<u32> {
    for (index, item) in sdl2::render::drivers().enumerate() {
        if item.name == "opengl" {
            return Some(index as u32);
        }
    }
    None
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem.window("Window", 800, 600)
        .opengl() // this line DOES NOT enable opengl, but allows you to create/get an OpenGL context from your window.
        .build()
        .unwrap();
    let canvas = window.into_canvas()
        .index(find_sdl_gl_driver().unwrap())
        .build()
        .unwrap();

    // ...
}

如果你不打算通过 gl-rs crate 使用 OpenGL 调用,你可以在这里停止。SDL2 将自动使用 OpenGL 后端

如果你打算在你的调用中混合使用 sdl2 调用,你需要首先使用画布的上下文


// initialization
gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);

// sdl::render creates a context for you, if you use a Canvas you need to use it.
canvas.window().gl_set_context_to_current();

// ... in the main loop ...
unsafe {
    gl::ClearColor(0.6, 0.0, 0.8, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
}
canvas.present();

但是请注意,sdl2 有其内部状态,你应该避免干扰。避免在 SDL2 调用过程中使用手动 OpenGL,或者确保恢复之前的状态。

手动使用 OpenGL 调用

extern crate sdl2;
extern crate gl;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile;

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    
    let gl_attr = video_subsystem.gl_attr();
    gl_attr.set_context_profile(GLProfile::Core);
    gl_attr.set_context_version(3, 3);

    let window = video_subsystem.window("Window", 800, 600)
        .opengl()
        .build()
        .unwrap();

    // Unlike the other example above, nobody created a context for your window, so you need to create one.
    let ctx = window.gl_create_context().unwrap();
    gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
    
    debug_assert_eq!(gl_attr.context_profile(), GLProfile::Core);
    debug_assert_eq!(gl_attr.context_version(), (3, 3));

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        unsafe {
            gl::ClearColor(0.6, 0.0, 0.8, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        window.gl_swap_window();
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        ::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60));
    }
}

如上所述,当你不关心 sdl2 的渲染能力,但关心其音频、控制器和其他 SDL2 的一些 neat 功能时,此方法非常有用。

你不必担心与 sdl2 或你不喜欢的版本混合状态:SDL2 永远不会在 render 模块之外调用任何 OpenGL 函数。

Vulkan

要使用 Vulkan,你需要一个 Rust 的 Vulkan 库。此示例使用 Vulkano 库。其他库可能使用不同的数据类型来表示原始 Vulkan 对象句柄。与 SDL2 的 Vulkan 函数接口的每个库的步骤都可能不同。

首先,确保你启用了 raw-window-handle 功能。

extern crate sdl2;
extern crate vulkano;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use vulkano::instance::{Instance, InstanceCreateInfo, InstanceExtensions};
use vulkano::swapchain::Surface;
use vulkano::VulkanLibrary;

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem
        .window("Window Title - My Vulkano-SDL2 application", 1024, 768)
        .vulkan()
        .build()
        .unwrap();

    let instance_extensions =
        InstanceExtensions::from_iter(window.vulkan_instance_extensions().unwrap());

    let instance = Instance::new(
        VulkanLibrary::new().unwrap(),
        InstanceCreateInfo {
            enabled_extensions: instance_extensions,
            ..Default::default()
        },
    )
    .unwrap();

    // SAFETY: Be sure not to drop the `window` before the `Surface` or vulkan `Swapchain`!
    // (SIGSEGV otherwise)
    let surface = unsafe { Surface::from_window_ref(instance.clone(), &window) };

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. }
                | Event::KeyDown {
                    keycode: Some(Keycode::Escape),
                    ..
                } => {
                    break 'running;
                }
                _ => {}
            }
        }
        ::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60));
    }
}

支持 raw-window-handle

可以使用特征名称启用 raw-window-handle

[dependencies.sdl2]
version = "0.37"
features = ["raw-window-handle"]

还有一个与 wgpu 一起工作的示例

cargo run --example raw-window-handle-with-wgpu --features raw-window-handle

macOS 上的 sdl2 与 raw-window-handle

在 macOS 上,RawWindowHandle.ns_view 字段返回 null。消耗 RawWindowHandle 的库(如 wgpu)应确定一个合理的默认值用于 ns_view。如果没有这样做,请向相关项目提交一个 issue。

Android 上的 raw-window-handle

在某些平台上,包括Android,即使没有创建渲染器,SDL2也会尝试自己创建OpenGL上下文。这可能导致在初始化Vulkan或GLES时出现错误,例如VK_ERROR_NATIVE_WINDOW_IN_USE_KHR。在创建窗口之前添加以下代码可修复错误:

sdl2::hint::set("SDL_VIDEO_EXTERNAL_CONTEXT", "1")

当出现问题时

Rust和Rust-SDL2都仍在积极开发中,使用时可能会遇到一些问题。在恐慌之前,请确保您正在使用Rust和Cargo的最新版本,并确保您已将Rust-SDL2更新到最新版本,然后运行cargo clean。如果这仍然失败,请在问题跟踪器上告诉我们。

贡献

任何Pull Request都受欢迎,无论您的贡献有多小!但是,贡献也有一些条件

  • 新功能必须有适当的文档,无论是通过示例还是通过内联文档(通过cargo doc)。文档必须面向最终用户以及您的下一个贡献者。
  • 破坏性更改必须有一个适当的论据。虽然该crate的1.0之前的版本允许我们保持一定的不稳定,但无用的破坏性更改将被拒绝
  • 通过Pull Request添加的次要更改、破坏性更改和新功能必须添加到更改日志文件中。现在在更改日志中记录您的更改是强制性的。在GitHub中包含对您的提交/拉取请求的简短描述和链接即可。内部更改、文档或元更改(travis构建更改、README说明更新等)无需添加到更改日志中。

lib.rs:

此crate主要是由bindgen生成的。在大多数情况下,这应该足够了,但如果您发现bindgen生成的内容与您的操作系统之间存在差异,您始终可以生成自己的sdl2-sys

依赖项