本工作室自主开发十多款实用软件,为纯绿色软件,安全可靠,不写注册表,不污染操作系统任何地方,绝不附带任何无关软件,绝不困绑任何插件,支持所有WindowsXP以上系统
论坛的首页 勇芳的软件
教程和帮助
  • VisualFreeBasic编程文档
  • 勇芳系列软件帮助说明教程
  • 留言或交流 登录
    登录
    侧边栏壁纸
    博主头像
    勇芳

    • 累计撰写 330 篇文章
    • 累计收到 0 条评论
    • 首页
    • 栏目
      • 论坛的首页
      • 勇芳的软件
      • 教程和帮助
        • VisualFreeBasic编程文档
        • 勇芳系列软件帮助说明教程
      • 留言或交流
      • 登录
    作者 【1】 的文章
    • SDL3_API分类参考_SDL_net 核心 API 集合(CategorySDLNet) 2026-3-7
      SDL3_API分类参考_SDL_net 核心 API 集合(CategorySDLNet) SDL_net 核心 API 集合(CategorySDLNet) SDL_net 是 SDL 官方的网络编程扩展库,它对 BSD Sockets、WinSock 等系统级网络 API 进行了轻量级封装,核心设计目标是简化网络编程复杂度、处理各类边界情况,让开发者无需关注底层协议细节即可实现网络通信。其核心设计理念包括:全异步非阻塞接口(可显式等待操作完成)、抽象化地址管理(屏蔽不同网络协议差异)、简洁优先且不失功能完整性。 核心概念与使用流程 初始化:调用 NET_Init() 初始化库,程序退出前调用 NET_Quit() 清理; 地址处理:通过 NET_ResolveHostname() 解析域名到 NET_Address 对象,或直接构造地址; 通信模式选择: TCP(流套接字):客户端用 NET_CreateClient() 连接服务器,服务器用 NET_CreateServer() 监听并通过 NET_AcceptClient() 接受连接,通过 NET_StreamSocket 收发数据; UDP(数据报套接字):用 NET_CreateDatagramSocket() 创建套接字,通过 NET_SendDatagram()/NET_ReceiveDatagram() 收发数据包; 异步操作:所有网络操作非阻塞,可通过 NET_WaitUntil*() 系列函数显式等待操作完成; 测试辅助:通过模拟网络异常函数(如丢包)测试恶劣网络环境下的程序表现。 核心 API 列表(按功能分类) 一、基础初始化与版本管理 NET_Init:初始化 SDL_net 库(必须调用,加载底层网络接口) NET_Quit:清理 SDL_net 所有资源(程序退出前必须调用) NET_Version:获取当前 SDL_net 版本信息 SDL_NET_MAJOR_VERSION:SDL_net 主版本号宏(如 3 代表 SDL_net 3.x) SDL_NET_MINOR_VERSION:SDL_net 次版本号宏 SDL_NET_MICRO_VERSION:SDL_net 修订版本号宏 SDL_NET_VERSION:构造版本结构体的宏 SDL_NET_VERSION_ATLEAST:编译期检查版本是否满足最低要求 二、网络地址(NET_Address)管理 1. 地址解析与创建 NET_ResolveHostname:异步解析域名/IP 到 NET_Address 对象(后台线程执行 DNS 查询) NET_GetLocalAddresses:获取本地主机的所有网络地址(返回 NET_Address 数组) NET_FreeLocalAddresses:释放 NET_GetLocalAddresses 返回的地址数组 2. 地址属性与操作 NET_GetAddressString:将 NET_Address 转换为可读的字符串(如 "192.168.1.1:8080") NET_GetAddressStatus:获取地址解析状态(未解析/解析成功/解析失败) NET_CompareAddresses:比较两个 NET_Address 是否指向同一网络地址 NET_RefAddress:增加 NET_Address 对象的引用计数(防止被提前释放) NET_UnrefAddress:减少 NET_Address 对象的引用计数,计数为 0 时自动释放 三、TCP 流套接字(StreamSocket)- 客户端 NET_CreateClient:创建 TCP 客户端套接字,发起对指定 NET_Address 的连接 NET_GetConnectionStatus:获取客户端连接状态(未连接/连接中/已连接/连接失败) NET_WaitUntilConnected:阻塞等待客户端连接完成(支持超时,可非阻塞查询/无限等待) NET_GetStreamSocketAddress:获取流套接字对应的远端 NET_Address NET_GetStreamSocketPendingWrites:获取流套接字待发送的字节数 NET_WriteToStreamSocket:向流套接字写入数据(非阻塞,返回实际写入字节数) NET_ReadFromStreamSocket:从流套接字读取数据(非阻塞,返回实际读取字节数) NET_WaitUntilInputAvailable:阻塞等待流套接字有可读数据(支持超时) NET_WaitUntilStreamSocketDrained:阻塞等待套接字待发送数据全部发送完成 NET_DestroyStreamSocket:销毁流套接字,关闭连接 四、TCP 服务器(NET_Server) NET_CreateServer:创建 TCP 服务器,监听指定 NET_Address 的端口 NET_AcceptClient:接受客户端连接(非阻塞,返回新的 NET_StreamSocket) NET_DestroyServer:销毁服务器,停止监听端口 五、UDP 数据报套接字(DatagramSocket) NET_CreateDatagramSocket:创建 UDP 数据报套接字(无连接,支持点对点通信) NET_SendDatagram:发送 UDP 数据包到指定 NET_Address(非阻塞) NET_ReceiveDatagram:接收 UDP 数据包(非阻塞,返回数据包和发送方地址) NET_DestroyDatagram:销毁接收到的 UDP 数据包,释放内存 NET_DestroyDatagramSocket:销毁 UDP 套接字 六、阻塞等待函数(异步操作显式等待) NET_WaitUntilResolved:阻塞等待地址解析完成(支持超时) NET_WaitUntilConnected:阻塞等待客户端连接完成 NET_WaitUntilInputAvailable:阻塞等待套接字有可读数据 NET_WaitUntilStreamSocketDrained:阻塞等待套接字发送缓冲区排空 七、网络异常模拟(测试专用) NET_SimulateAddressResolutionLoss:模拟地址解析失败(测试 DNS 异常) NET_SimulateStreamPacketLoss:模拟 TCP 流数据包丢失(测试网络不稳定) NET_SimulateDatagramPacketLoss:模拟 UDP 数据包丢失(测试丢包场景) 八、状态枚举(NET_Status) 核心状态值(隐含在 NET_Status 枚举中): NET_STATUS_INVALID:无效状态(未初始化/已销毁) NET_STATUS_RESOLVING:地址解析中 NET_STATUS_RESOLVED:地址解析成功 NET_STATUS_RESOLVE_FAILED:地址解析失败 NET_STATUS_CONNECTING:连接建立中 NET_STATUS_CONNECTED:连接已建立 NET_STATUS_CONNECT_FAILED:连接建立失败 数据类型(Datatypes) NET_Address:网络地址抽象对象(封装 IP 地址、端口、协议等信息) NET_DatagramSocket:UDP 数据报套接字对象(无连接,用于收发数据包) NET_Server:TCP 服务器对象(监听端口,接受客户端连接) NET_StreamSocket:TCP 流套接字对象(面向连接,可靠的字节流传输) 结构体(Structs) NET_Datagram:UDP 数据包结构体(包含数据缓冲区、数据长度、发送方地址) 宏定义(Macros) SDL_NET_MAJOR_VERSION / SDL_NET_MINOR_VERSION / SDL_NET_MICRO_VERSION:版本号宏 SDL_NET_VERSION:构造 SDL_version 结构体的宏 SDL_NET_VERSION_ATLEAST:版本检查宏(如 SDL_NET_VERSION_ATLEAST(3,0,0)) FreeBASIC 示例代码 ' 引入 SDL 及 SDL_net 相关声明(需链接 SDL3 和 SDL3_net 库) #Include "SDL.bi" #Include "SDL_net.bi" ' 补充关键常量/类型声明(FreeBASIC 绑定可能缺失) #Define NET_PORT_ANY 0 Type NET_Status value As Integer End Type Enum NET_Status_Values NET_STATUS_INVALID = 0 NET_STATUS_RESOLVING NET_STATUS_RESOLVED NET_STATUS_CONNECT_FAILED NET_STATUS_CONNECTING NET_STATUS_CONNECTED End Enum ' 检查 SDL_net 版本 Sub CheckNetVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【检查 SDL_net 版本】") Dim As SDL_version ver NET_Version(@ver) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_net 版本:%d.%d.%d", ver.major, ver.minor, ver.patch) ' 编译期版本检查 #If SDL_NET_VERSION_ATLEAST(3, 0, 0) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 满足 SDL_net 3.0.0 最低版本要求") #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 不满足 SDL_net 3.0.0 最低版本要求") #EndIf End Sub ' TCP 服务器示例(简单回显服务器) Sub TCPServerExample(ByVal port As Uint16) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【TCP 回显服务器示例】") ' 1. 初始化 SDL_net If (NET_Init() = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_net 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 2. 构造服务器地址(监听所有网卡的指定端口) Dim As NET_Address Ptr serverAddr = NET_ResolveHostname(NULL, port) If (serverAddr = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "解析地址失败:%s", SDL_GetError()) NET_Quit() Exit Sub End If ' 等待地址解析完成 If (NET_WaitUntilResolved(serverAddr, -1) = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "地址解析超时") NET_UnrefAddress(serverAddr) NET_Quit() Exit Sub End If ' 3. 创建 TCP 服务器 Dim As NET_Server Ptr server = NET_CreateServer(serverAddr) If (server = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建服务器失败:%s", SDL_GetError()) NET_UnrefAddress(serverAddr) NET_Quit() Exit Sub End If NET_UnrefAddress(serverAddr) ' 释放地址引用 Dim As ZString * 256 addrStr NET_GetAddressString(serverAddr, addrStr, sizeof(addrStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "服务器已启动,监听地址:%s", addrStr) ' 4. 接受客户端连接并处理 Dim As NET_StreamSocket Ptr clientSocket = NULL Dim As SDL_bool running = SDL_TRUE Dim As UByte buffer(1023) ' 1KB 接收缓冲区 While (running) ' 非阻塞接受客户端连接 clientSocket = NET_AcceptClient(server) If (clientSocket <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "客户端已连接") ' 循环接收并回显数据 While (running) ' 等待有可读数据(超时 100ms) If (NET_WaitUntilInputAvailable(clientSocket, 100) = SDL_TRUE) Then ' 读取数据 Dim As Sint64 readBytes = NET_ReadFromStreamSocket(clientSocket, @buffer(0), sizeof(buffer)) If (readBytes > 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "收到数据:%.*s", readBytes, @buffer(0)) ' 回显数据给客户端 Dim As Sint64 writeBytes = NET_WriteToStreamSocket(clientSocket, @buffer(0), readBytes) If (writeBytes < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "发送数据失败:%s", SDL_GetError()) Exit While End If ElseIf (readBytes = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "客户端断开连接") Exit While Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "读取数据失败:%s", SDL_GetError()) Exit While End If End If ' 处理退出事件(简化示例,实际需处理 SDL 事件) Dim As SDL_Event evt If (SDL_PollEvent(@evt) AndAlso evt.type = SDL_QUIT) Then running = SDL_FALSE End If Wend ' 关闭客户端连接 NET_DestroyStreamSocket(clientSocket) clientSocket = NULL End If ' 处理退出事件 Dim As SDL_Event evt If (SDL_PollEvent(@evt) AndAlso evt.type = SDL_QUIT) Then running = SDL_FALSE End If SDL_Delay(10) Wend ' 5. 释放资源 If (clientSocket <> NULL) Then NET_DestroyStreamSocket(clientSocket) End If NET_DestroyServer(server) NET_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "服务器已停止") End Sub ' TCP 客户端示例 Sub TCPClientExample(ByVal hostname As ZString Ptr, ByVal port As Uint16) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【TCP 客户端示例】") ' 1. 初始化 SDL_net If (NET_Init() = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_net 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 2. 解析服务器地址 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析地址:%s:%d", hostname, port) Dim As NET_Address Ptr serverAddr = NET_ResolveHostname(hostname, port) If (serverAddr = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "解析地址失败:%s", SDL_GetError()) NET_Quit() Exit Sub End If ' 等待地址解析完成(无限等待) If (NET_WaitUntilResolved(serverAddr, -1) = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "地址解析失败") NET_UnrefAddress(serverAddr) NET_Quit() Exit Sub End If ' 打印解析后的地址 Dim As ZString * 256 addrStr NET_GetAddressString(serverAddr, addrStr, sizeof(addrStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析完成:%s", addrStr) ' 3. 创建客户端并连接服务器 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "连接服务器...") Dim As NET_StreamSocket Ptr clientSocket = NET_CreateClient(serverAddr) If (clientSocket = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建客户端失败:%s", SDL_GetError()) NET_UnrefAddress(serverAddr) NET_Quit() Exit Sub End If NET_UnrefAddress(serverAddr) ' 等待连接完成(超时 5 秒) If (NET_WaitUntilConnected(clientSocket, 5000) = SDL_FALSE) Then Dim As NET_Status status NET_GetConnectionStatus(clientSocket, @status) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "连接失败,状态:%d", status.value) NET_DestroyStreamSocket(clientSocket) NET_Quit() Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "连接成功!") ' 4. 发送测试数据 Dim As ZString * 64 sendData = "Hello SDL_net Server!" Dim As Sint64 writeBytes = NET_WriteToStreamSocket(clientSocket, sendData, Len(sendData)) If (writeBytes < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "发送数据失败:%s", SDL_GetError()) NET_DestroyStreamSocket(clientSocket) NET_Quit() Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "发送数据:%s", sendData) ' 5. 接收服务器回显数据 Dim As UByte recvBuffer(1023) If (NET_WaitUntilInputAvailable(clientSocket, 2000) = SDL_TRUE) Then Dim As Sint64 readBytes = NET_ReadFromStreamSocket(clientSocket, @recvBuffer(0), sizeof(recvBuffer)) If (readBytes > 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "收到回显:%.*s", readBytes, @recvBuffer(0)) End If Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "接收超时") End If ' 6. 等待数据发送完成并关闭连接 NET_WaitUntilStreamSocketDrained(clientSocket, -1) NET_DestroyStreamSocket(clientSocket) NET_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "客户端已断开连接") End Sub ' UDP 通信示例(简单点对点发送) Sub UDPCommunicationExample(ByVal localPort As Uint16, ByVal targetHost As ZString Ptr, ByVal targetPort As Uint16) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【UDP 通信示例】") ' 1. 初始化 SDL_net If (NET_Init() = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_net 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 2. 创建 UDP 套接字 Dim As NET_Address Ptr localAddr = NET_ResolveHostname(NULL, localPort) Dim As NET_DatagramSocket Ptr udpSocket = NET_CreateDatagramSocket(localAddr) NET_UnrefAddress(localAddr) If (udpSocket = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建 UDP 套接字失败:%s", SDL_GetError()) NET_Quit() Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "UDP 套接字已创建,监听端口:%d", localPort) ' 3. 解析目标地址 Dim As NET_Address Ptr targetAddr = NET_ResolveHostname(targetHost, targetPort) If (NET_WaitUntilResolved(targetAddr, 3000) = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "解析目标地址失败") NET_UnrefAddress(targetAddr) NET_DestroyDatagramSocket(udpSocket) NET_Quit() Exit Sub End If ' 4. 发送 UDP 数据包 Dim As ZString * 64 sendData = "Hello UDP Peer!" If (NET_SendDatagram(udpSocket, targetAddr, sendData, Len(sendData)) = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "发送 UDP 数据包失败:%s", SDL_GetError()) Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "发送 UDP 数据:%s", sendData) End If ' 5. 尝试接收响应(超时 2 秒) Dim As NET_Datagram Ptr datagram = NULL Dim As UByte recvBuffer(1023) If (NET_ReceiveDatagram(udpSocket, @datagram, 2000) = SDL_TRUE AndAlso datagram <> NULL) Then ' 提取数据包数据 Dim As Const UByte Ptr data = NET_DatagramGetData(datagram) Dim As Sint64 len = NET_DatagramGetLength(datagram) Dim As NET_Address Ptr senderAddr = NET_DatagramGetAddress(datagram) Dim As ZString * 256 senderStr NET_GetAddressString(senderAddr, senderStr, sizeof(senderStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "从 %s 收到 UDP 数据:%.*s", senderStr, len, data) NET_DestroyDatagram(datagram) Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "未收到 UDP 响应(超时)") End If ' 6. 释放资源 NET_UnrefAddress(targetAddr) NET_DestroyDatagramSocket(udpSocket) NET_Quit() End Sub ' 主程序 Sub Main() ' 初始化 SDL 核心 If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例(按需取消注释) CheckNetVersion() ' TCPServerExample(8080) ' 先启动服务器 ' TCPClientExample(StrPtr("127.0.0.1"), 8080) ' 再启动客户端 ' UDPCommunicationExample(8081, StrPtr("127.0.0.1"), 8082) ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 异步非阻塞核心: SDL_net 所有操作默认非阻塞,调用后立即返回,需通过状态查询(如 NET_GetConnectionStatus)或 NET_WaitUntil*() 等待操作完成; 阻塞函数(NET_WaitUntil*)建议在后台线程使用,避免阻塞主线程(如游戏渲染线程)。 TCP vs UDP 选择: TCP(流套接字):可靠的字节流传输,自动重传丢失数据、保证顺序,适合需要数据完整性的场景(如登录、文件传输); UDP(数据报套接字):无连接、不可靠,数据包可能丢失/乱序,但延迟低、开销小,适合实时性要求高的场景(如游戏帧同步、语音)。 地址引用计数: NET_Address 采用引用计数管理,NET_RefAddress 增加计数,NET_UnrefAddress 减少计数; 确保不再使用的地址调用 NET_UnrefAddress,避免内存泄漏。 网络异常模拟: NET_Simulate*Loss 系列函数用于测试恶劣网络环境,仅在开发/测试阶段使用,生产环境需禁用; 可模拟 DNS 解析失败、TCP/UDP 丢包,验证程序的容错能力。 跨平台注意事项: Windows 系统需确保防火墙允许程序访问网络,监听端口需配置入站规则; Linux/macOS 需注意端口权限(1024 以下端口需 root 权限); 移动平台(Android/iOS)需申请网络权限:Android 需 INTERNET 权限,iOS 需关闭 ATS(或配置例外)。 总结 核心优势: 轻量级封装系统套接字 API,屏蔽跨平台差异(Windows/ Linux/macOS/移动端); 全异步非阻塞设计,适配游戏/实时应用的主线程模型; 抽象化地址管理,无需关注 IPv4/IPv6 底层细节; 内置网络异常模拟功能,便于测试程序的鲁棒性; 与 SDL 生态无缝集成,可直接结合 SDL 事件循环使用。 使用建议: 网络操作尽量放在后台线程,避免阻塞主线程; TCP 通信需处理连接断开、超时等异常,UDP 需自行实现重传/校验逻辑; 频繁使用的 NET_Address 需合理管理引用计数,避免内存泄漏; 服务器监听端口时,优先使用 NET_PORT_ANY 自动分配端口,或选择 1024 以上的非特权端口; 生产环境禁用网络异常模拟函数,避免影响正常通信。 关键点回顾: SDL_net 核心是抽象化的地址(NET_Address)、套接字(TCP 流/UDP 数据报)、服务器(NET_Server)三层结构; NET_Init()/NET_Quit() 是必选的初始化/清理接口; TCP 适合可靠传输,UDP 适合实时传输,需根据业务场景选择; 所有操作默认非阻塞,可通过 NET_WaitUntil*() 显式等待; 地址对象采用引用计数管理,需正确调用 NET_RefAddress/NET_UnrefAddress。
      • 2026年-3月-7日
      • 3 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_SDL_mixer 核心 API 集合(CategorySDLMixer) 2026-3-7
      SDL3_API分类参考_SDL_mixer 核心 API 集合(CategorySDLMixer) SDL_mixer 核心 API 集合(CategorySDLMixer) SDL_mixer 是 SDL 官方的音频混音扩展库,旨在简化复杂的音频处理任务。它提供音频文件解码、多音效混音、基础 3D 定位音频、各类音频特效等核心能力,支持实时混音输出到多个音频设备,也可将混音数据生成到内存缓冲区,甚至能同时完成这两种操作,是 SDL 生态中处理音频播放与混音的核心工具。 核心概念与使用流程 初始化:调用 MIX_Init() 初始化库,指定支持的音频格式; 创建混音器:通过 MIX_CreateMixerDevice()(输出到硬件)或 MIX_CreateMixer()(输出到内存)创建混音器实例; 加载音频:使用 MIX_LoadAudio() 加载音频文件为可复用的 MIX_Audio 对象; 创建轨道:通过 MIX_CreateTrack() 创建音频轨道(每轨道对应一个同时播放的音效); 绑定音频:用 MIX_SetTrackAudio() 将音频数据绑定到轨道; 播放控制:调用 MIX_PlayTrack() 播放轨道,支持循环、淡入淡出等效果; 高级控制:可设置轨道音量、3D 位置、播放速度,或通过标签批量控制多轨道; 清理:使用完毕后销毁轨道、混音器,调用 MIX_Quit() 释放资源。 核心 API 列表(按功能分类) 一、基础初始化与版本管理 MIX_Init:初始化 SDL_mixer 库(需指定支持的音频格式,如 MP3/OGG 等) MIX_Quit:清理 SDL_mixer 所有资源(程序退出前必须调用) MIX_Version:获取当前 SDL_mixer 版本信息 SDL_MIXER_MAJOR_VERSION:SDL_mixer 主版本号宏(如 3 代表 SDL_mixer 3.x) SDL_MIXER_MINOR_VERSION:SDL_mixer 次版本号宏 SDL_MIXER_MICRO_VERSION:SDL_mixer 修订版本号宏 SDL_MIXER_VERSION:构造版本结构体的宏 SDL_MIXER_VERSION_ATLEAST:编译期检查版本是否满足最低要求 二、音频数据(MIX_Audio)管理 1. 音频加载/销毁 MIX_LoadAudio:从文件加载音频数据为 MIX_Audio 对象(自动解码) MIX_LoadAudio_IO:从 SDL_IOStream 流加载音频数据 MIX_LoadAudioWithProperties:带自定义属性加载音频(如采样率、声道数) MIX_LoadAudioNoCopy:加载音频但不复制数据(直接使用内存缓冲区) MIX_LoadRawAudio:加载原始 PCM 音频数据(无需解码) MIX_LoadRawAudio_IO:从流加载原始 PCM 音频 MIX_LoadRawAudioNoCopy:加载原始 PCM 音频且不复制数据 MIX_CreateSineWaveAudio:生成正弦波音频数据(用于测试/音效生成) MIX_DestroyAudio:销毁 MIX_Audio 对象,释放音频数据 2. 音频属性查询 MIX_GetAudioFormat:获取音频的 PCM 格式(如 SDL_AUDIO_F32、SDL_AUDIO_S16) MIX_GetAudioDuration:获取音频总时长(采样帧数) MIX_GetAudioProperties:获取音频的元数据(如 ID3 标签、时长、码率等) MIX_AudioFramesToMS:将音频的采样帧数转换为毫秒 MIX_AudioMSToFrames:将毫秒转换为音频的采样帧数 三、音频解码器(MIX_AudioDecoder) MIX_CreateAudioDecoder:创建音频解码器实例(通用接口) MIX_CreateAudioDecoder_IO:从 SDL_IOStream 流创建解码器 MIX_DestroyAudioDecoder:销毁解码器实例 MIX_DecodeAudio:解码音频数据到 PCM 格式 MIX_GetAudioDecoder:获取指定索引的解码器名称(如 "mp3"、"ogg") MIX_GetNumAudioDecoders:获取支持的解码器总数 MIX_GetAudioDecoderFormat:获取解码器输出的 PCM 格式 MIX_GetAudioDecoderProperties:获取解码器配置属性 四、混音器(MIX_Mixer)管理 1. 混音器创建/销毁 MIX_CreateMixer:创建内存混音器(输出到内存缓冲区) MIX_CreateMixerDevice:创建设备混音器(输出到音频硬件) MIX_DestroyMixer:销毁混音器实例 MIX_LockMixer:锁定混音器(防止多线程操作冲突) MIX_UnlockMixer:解锁混音器 2. 混音器属性控制 MIX_GetMixerFormat:获取混音器输出的 PCM 格式 MIX_GetMixerGain:获取混音器主音量增益(0.0~1.0) MIX_SetMixerGain:设置混音器主音量增益 MIX_GetMixerFrequencyRatio:获取混音器输出的播放速度比例 MIX_SetMixerFrequencyRatio:设置播放速度比例(>1 加速,<1 减速,同步调整音调) MIX_GetMixerProperties:获取混音器完整配置属性 MIX_SetPostMixCallback:设置混音后回调(处理最终输出的 PCM 数据) MIX_Generate:手动触发混音器生成音频数据(内存混音器专用) 五、音频轨道(MIX_Track)管理 1. 轨道创建/销毁 MIX_CreateTrack:创建音频轨道(混音器的核心播放单元) MIX_DestroyTrack:销毁轨道实例 2. 轨道输入绑定 MIX_SetTrackAudio:将 MIX_Audio 绑定到轨道(播放预加载的音频) MIX_SetTrackAudioStream:将 SDL_AudioStream 绑定到轨道(流式播放) MIX_SetTrackIOStream:将 SDL_IOStream 绑定到轨道(实时解码播放) MIX_SetTrackRawIOStream:绑定原始 PCM 数据流到轨道 3. 播放控制 MIX_PlayTrack:播放轨道(支持循环次数、淡入淡出、起始位置等参数) MIX_PlayAudio:快速播放 MIX_Audio(自动创建临时轨道) MIX_PauseTrack:暂停指定轨道 MIX_ResumeTrack:恢复暂停的轨道 MIX_StopTrack:停止轨道播放 MIX_PauseAllTracks:暂停所有轨道 MIX_ResumeAllTracks:恢复所有轨道 MIX_StopAllTracks:停止所有轨道 MIX_TrackPlaying:检查轨道是否正在播放 MIX_TrackPaused:检查轨道是否处于暂停状态 4. 轨道属性控制 MIX_GetTrackGain:获取轨道音量增益 MIX_SetTrackGain:设置轨道音量增益(独立于主音量) MIX_GetTrackFrequencyRatio:获取轨道播放速度比例 MIX_SetTrackFrequencyRatio:设置轨道播放速度(同步调整音调) MIX_GetTrackLoops:获取轨道循环次数 MIX_SetTrackLoops:设置轨道循环次数(0=播放1次,-1=无限循环) MIX_GetTrackFadeFrames:获取轨道淡入/淡出的采样帧数 MIX_SetTrackOutputChannelMap:设置轨道输出声道映射(调整音频输出到指定扬声器) MIX_GetTrackPlaybackPosition:获取轨道当前播放位置(采样帧) MIX_SetTrackPlaybackPosition:设置轨道播放位置(定位到指定帧) MIX_GetTrackRemaining:获取轨道剩余播放帧数 5. 3D 与立体声控制 MIX_SetTrack3DPosition:设置轨道的 3D 空间位置(支持距离衰减、空间化) MIX_GetTrack3DPosition:获取轨道的 3D 位置 MIX_SetTrackStereo:设置轨道的立体声平衡(左右声道音量比例) 6. 轨道标签与批量控制 MIX_TagTrack:为轨道添加自定义标签(如 "music"、"ui_sfx") MIX_UntagTrack:移除轨道的指定标签 MIX_GetTrackTags:获取轨道的所有标签 MIX_GetTaggedTracks:获取指定标签的所有轨道 MIX_PlayTag:播放所有带指定标签的轨道 MIX_PauseTag:暂停所有带指定标签的轨道 MIX_ResumeTag:恢复所有带指定标签的轨道 MIX_StopTag:停止所有带指定标签的轨道 MIX_SetTagGain:设置指定标签所有轨道的音量增益 7. 轨道回调函数 MIX_SetTrackRawCallback:设置原始音频回调(解码后、未处理前的 PCM 数据) MIX_SetTrackCookedCallback:设置处理后音频回调(应用淡入淡出、3D 等效果后的 PCM 数据) MIX_SetTrackStoppedCallback:设置轨道播放结束回调 8. 时间转换 MIX_TrackFramesToMS:将轨道的采样帧数转换为毫秒 MIX_TrackMSToFrames:将毫秒转换为轨道的采样帧数 MIX_FramesToMS:通用的帧数转毫秒 MIX_MSToFrames:通用的毫秒转帧数 六、音频组(MIX_Group)管理 MIX_CreateGroup:创建音频组(管理一组轨道,单独混音) MIX_DestroyGroup:销毁音频组 MIX_SetTrackGroup:将轨道加入指定音频组 MIX_GetGroupMixer:获取音频组的混音器实例 MIX_GetGroupProperties:获取音频组属性 MIX_SetGroupPostMixCallback:设置音频组混音后回调(处理组内轨道的混音数据) 七、通用工具函数 MIX_GetTrackMixer:获取轨道所属的混音器 MIX_GetTrackAudio:获取轨道绑定的 MIX_Audio 对象 MIX_GetTrackAudioStream:获取轨道绑定的音频流 数据类型(Datatypes) MIX_Audio:封装解码后的音频数据(PCM 数据、格式、时长等) MIX_AudioDecoder:音频解码器实例(用于解码各类音频格式) MIX_Group:音频组对象(管理一组轨道,支持独立混音) MIX_GroupMixCallback:音频组混音回调函数类型 MIX_Mixer:混音器实例(核心混音单元,分设备/内存两种) MIX_PostMixCallback:混音后回调函数类型(处理最终输出数据) MIX_Track:音频轨道对象(混音器的播放单元,每轨道对应一个音效) MIX_TrackMixCallback:轨道音频回调函数类型(处理原始/处理后数据) MIX_TrackStoppedCallback:轨道播放结束回调函数类型 结构体(Structs) MIX_Point3D:3D 空间坐标结构体(用于设置轨道的 3D 位置) MIX_StereoGains:立体声增益结构体(左右声道音量比例) FreeBASIC 示例代码 ' 引入 SDL 及 SDL_mixer 相关声明(需链接 SDL3 和 SDL3_mixer 库) #Include "SDL.bi" #Include "SDL_mixer.bi" ' 补充关键常量/类型声明(FreeBASIC 绑定可能缺失) #Define MIX_INIT_MP3 1 #Define MIX_INIT_OGG 2 Type MIX_Point3D x As Float y As Float z As Float End Type ' 检查 SDL_mixer 版本 Sub CheckMixerVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【检查 SDL_mixer 版本】") Dim As SDL_version ver MIX_Version(@ver) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_mixer 版本:%d.%d.%d", ver.major, ver.minor, ver.patch) ' 编译期版本检查 #If SDL_MIXER_VERSION_ATLEAST(3, 0, 0) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 满足 SDL_mixer 3.0.0 最低版本要求") #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 不满足 SDL_mixer 3.0.0 最低版本要求") #EndIf End Sub ' 轨道播放结束回调函数 Sub TrackStoppedCallback Cdecl (ByVal track As MIX_Track Ptr, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【回调】轨道播放结束!") End Sub ' 基础音频播放示例 Sub BasicAudioPlaybackExample(ByVal audioPath As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【基础音频播放示例】") ' 1. 初始化 SDL_mixer(支持 MP3 和 OGG) Dim As Integer initFlags = MIX_INIT_MP3 Or MIX_INIT_OGG If (MIX_Init(initFlags) <> initFlags) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_mixer 初始化失败:%s", MIX_GetError()) Exit Sub End If ' 2. 创建设备混音器(输出到默认音频设备) Dim As MIX_Mixer Ptr mixer = MIX_CreateMixerDevice(NULL) If (mixer = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建混音器失败:%s", MIX_GetError()) MIX_Quit() Exit Sub End If ' 3. 加载音频文件 Dim As MIX_Audio Ptr audio = MIX_LoadAudio(audioPath) If (audio = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载音频失败:%s", MIX_GetError()) MIX_DestroyMixer(mixer) MIX_Quit() Exit Sub End If ' 4. 查询音频属性 Dim As Uint32 audioFormat Dim As Integer freq, channels MIX_GetAudioFormat(audio, @audioFormat, @freq, @channels) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "音频格式:%u, 采样率:%d Hz, 声道数:%d", audioFormat, freq, channels) Dim As Uint64 totalFrames = MIX_GetAudioDuration(audio) Dim As Uint64 totalMS = MIX_AudioFramesToMS(audio, totalFrames) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "音频时长:%llu 帧 / %llu 毫秒", totalFrames, totalMS) ' 5. 创建音频轨道 Dim As MIX_Track Ptr track = MIX_CreateTrack(mixer) If (track = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建轨道失败:%s", MIX_GetError()) MIX_DestroyAudio(audio) MIX_DestroyMixer(mixer) MIX_Quit() Exit Sub End If ' 6. 配置轨道 MIX_SetTrackAudio(track, audio) ' 绑定音频数据 MIX_SetTrackGain(track, 0.8) ' 设置轨道音量(80%) MIX_SetTrackLoops(track, 1) ' 循环1次(总共播放2次) MIX_SetTrackStoppedCallback(track, @TrackStoppedCallback, NULL) ' 设置结束回调 MIX_TagTrack(track, "music") ' 添加标签 ' 7. 设置 3D 位置(右侧 2 米处) Dim As MIX_Point3D pos = {2.0, 0.0, 0.0} MIX_SetTrack3DPosition(track, @pos) ' 8. 播放轨道 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "开始播放音频...") If (MIX_PlayTrack(track, 0, 0, 0) = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "播放轨道失败:%s", MIX_GetError()) End If ' 9. 等待播放完成(简单演示,实际项目需用事件循环) While (MIX_TrackPlaying(track)) SDL_Delay(100) ' 打印当前播放进度 Dim As Uint64 currFrames = MIX_GetTrackPlaybackPosition(track) Dim As Uint64 currMS = MIX_TrackFramesToMS(track, currFrames) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "播放进度:%llu/%llu 毫秒", currMS, totalMS) Wend ' 10. 释放资源 MIX_DestroyTrack(track) MIX_DestroyAudio(audio) MIX_DestroyMixer(mixer) MIX_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "音频播放完成") End Sub ' 批量控制带标签的轨道示例 Sub TagBasedControlExample(ByVal mixer As MIX_Mixer Ptr, ByVal sfxPath As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【标签批量控制示例】") ' 1. 加载音效并创建多个带 "ui_sfx" 标签的轨道 Dim As MIX_Audio Ptr sfxAudio = MIX_LoadAudio(sfxPath) If (sfxAudio = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载音效失败:%s", MIX_GetError()) Exit Sub End If ' 创建3个UI音效轨道 For i As Integer = 0 To 2 Dim As MIX_Track Ptr track = MIX_CreateTrack(mixer) If (track <> NULL) Then MIX_SetTrackAudio(track, sfxAudio) MIX_SetTrackGain(track, 0.5) MIX_TagTrack(track, "ui_sfx") End If Next ' 2. 批量播放所有 "ui_sfx" 标签的轨道 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "批量播放 UI 音效...") MIX_PlayTag(mixer, "ui_sfx", 0, 0, 0) ' 3. 延迟后批量暂停 SDL_Delay(500) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "批量暂停 UI 音效...") MIX_PauseTag(mixer, "ui_sfx") ' 4. 延迟后批量恢复 SDL_Delay(500) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "批量恢复 UI 音效...") MIX_ResumeTag(mixer, "ui_sfx") ' 5. 等待播放完成 SDL_Delay(1000) ' 6. 释放资源 MIX_DestroyAudio(sfxAudio) End Sub ' 主程序 Sub Main() ' 初始化 SDL 音频子系统 If (SDL_Init(SDL_INIT_AUDIO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 CheckMixerVersion() BasicAudioPlaybackExample(StrPtr("background_music.mp3")) ' 替换为实际音频文件路径 ' TagBasedControlExample(mixer, StrPtr("ui_click.wav")) ' 需先创建混音器,此处仅演示 ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 采样帧与时间转换: SDL_mixer 中所有时间计算基于「采样帧」(Sample Frame),而非毫秒,确保采样级精度; 立体声 16 位 PCM 音频:1 帧 = 2 采样 × 2 字节 = 4 字节; 不同采样率的音频,相同毫秒对应的帧数不同,需用 MIX_TrackMSToFrames() 等函数转换。 混音器类型选择: 设备混音器(MIX_CreateMixerDevice):输出到音频硬件,适合实时播放; 内存混音器(MIX_CreateMixer):输出到内存缓冲区,适合音频录制、离线处理。 3D 音频限制: SDL_mixer 仅提供基础 3D 定位(距离衰减、立体声空间化),不支持复杂的 3D 音效(如混响、遮挡); 如需专业 3D 音频,建议搭配 OpenAL 等专用库; 3D 效果仅在立体声/环绕声设备上生效,单声道设备无效果。 性能优化要点: 复用 MIX_Audio 对象(加载一次,多次播放),避免重复解码; 复用轨道对象(播放不同音频时仅需调用 MIX_SetTrackAudio()); 大量音效播放时使用标签批量控制,减少循环遍历; 多线程操作混音器时必须调用 MIX_LockMixer()/MIX_UnlockMixer() 加锁。 跨平台注意事项: Windows/macOS 支持主流音频格式(MP3/OGG/WAV/FLAC),Linux 需确保安装对应解码器; 移动平台需将音频文件放入 assets 目录,使用绝对路径加载; 音频设备权限:Android/iOS 需申请音频播放权限(Android 13+ 需 POST_NOTIFICATIONS 权限)。 总结 核心优势: 一站式音频解决方案:解码、混音、播放、特效全覆盖,无需集成多个音频库; 无缝衔接 SDL 核心库,与 SDL 窗口/事件系统兼容; 支持多轨道混音、3D 定位、播放速度调整等常用功能,满足游戏/多媒体开发需求; 高精度时间控制(采样帧级),支持实时/离线混音; 灵活的回调机制,可自定义音频处理逻辑。 使用建议: 初始化时仅加载需要的解码器(减少内存占用); 预加载常用音频为 MIX_Audio 对象,播放时复用轨道; 音效分类管理:用标签区分音乐、UI 音效、环境音效,方便批量控制; 实时音频处理(如音效滤镜)可通过 Raw/Cooked 回调实现; 避免在主线程中长时间阻塞,建议用回调/事件处理播放状态。 关键点回顾: SDL_mixer 是 SDL 的音频混音扩展库,核心是混音器(Mixer)、轨道(Track)、音频数据(Audio)三层结构; MIX_Init()/MIX_Quit() 是必选的初始化/清理接口,需指定支持的音频格式; 轨道是播放的基本单元,支持音量、速度、3D 位置、标签等配置; 时间计算基于采样帧,需通过专用函数转换为毫秒; 标签功能可批量控制多轨道,适合游戏中按类型管理音效。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_SDL_ttf 核心 API 集合(CategoryAPI) 2026-3-7
      SDL3_API分类参考_SDL_ttf 核心 API 集合(CategoryAPI) SDL_ttf 核心 API 集合(CategoryAPI) SDL_ttf 是 SDL 的官方字体渲染扩展库,该分类汇总了 SDL_ttf 全量核心 API,涵盖字体加载/管理、文本渲染(Surface/Renderer/GPU 三种模式)、字形/排版控制、多语言文本处理等功能,是 SDL 生态中实现高质量文本渲染的核心接口集合。 核心 API 列表(按功能分类) 一、基础初始化与版本管理 TTF_Init:初始化 SDL_ttf 库(必须调用,加载 FreeType/HarfBuzz 依赖) TTF_Quit:清理 SDL_ttf 资源(程序退出前调用) TTF_WasInit:检查 SDL_ttf 是否已初始化 TTF_Version:获取当前 SDL_ttf 版本信息 SDL_TTF_MAJOR_VERSION:SDL_ttf 主版本号宏(如 3 代表 SDL_ttf 3.x) SDL_TTF_VERSION:构造版本结构体的宏 SDL_TTF_VERSION_ATLEAST:编译期检查 SDL_ttf 版本是否满足最低要求 TTF_GetFreeTypeVersion:获取底层 FreeType 库版本 TTF_GetHarfBuzzVersion:获取底层 HarfBuzz 排版库版本 二、字体对象(TTF_Font)管理 1. 字体加载/释放 TTF_OpenFont:从文件加载字体文件(指定字号) TTF_OpenFontIO:从 SDL_IOStream 流加载字体(支持内存字体) TTF_OpenFontWithProperties:带自定义属性加载字体(如 DPI、字体面索引) TTF_CloseFont:关闭并释放字体对象 TTF_CopyFont:复制字体对象(继承原字体的样式/属性) TTF_GetNumFontFaces:获取字体文件中的字体面数量(多字体面文件专用) 2. 字体属性查询 TTF_FontHasGlyph:检查字体是否包含指定 Unicode 字形 TTF_FontIsFixedWidth:检查字体是否为等宽字体(如 Consolas) TTF_FontIsScalable:检查字体是否为可缩放矢量字体(如 TrueType) TTF_GetFontAscent:获取字体上行高度(基线到字形顶部的距离) TTF_GetFontDescent:获取字体下行高度(基线到字形底部的距离) TTF_GetFontHeight:获取字体总高度(上行+下行) TTF_GetFontLineSkip:获取字体行间距(两行文本的基线间距) TTF_GetFontFamilyName:获取字体家族名称(如 "Microsoft YaHei") TTF_GetFontStyleName:获取字体样式名称(如 "Bold") TTF_GetFontSize:获取字体当前字号 TTF_GetFontWeight:获取字体字重(粗细程度) TTF_GetFontStyle:获取字体样式标志(粗体/斜体等) TTF_GetFontDPI:获取字体渲染的 DPI 设置 TTF_GetFontCharSpacing:获取字符间距 TTF_GetFontKerning:获取字距调整开关状态 TTF_GetFontOutline:获取字体描边宽度 TTF_GetFontHinting:获取字体提示模式(影响渲染清晰度) TTF_GetFontDirection:获取字体默认排版方向 TTF_GetFontWrapAlignment:获取文本换行对齐方式 TTF_GetFontProperties:获取字体完整配置属性 3. 字体属性设置 TTF_SetFontSize:设置字体字号 TTF_SetFontSizeDPI:按 DPI 缩放设置字体字号 TTF_SetFontStyle:设置字体样式(粗体/斜体/下划线等) TTF_SetFontWeight:设置字体字重(如 TTF_FONT_WEIGHT_BOLD) TTF_SetFontCharSpacing:设置字符间距 TTF_SetFontKerning:开启/关闭字距调整(优化字符间距) TTF_SetFontOutline:设置字体描边宽度 TTF_SetFontHinting:设置字体提示模式(如 TTF_HINTING_NORMAL) TTF_SetFontDirection:设置字体排版方向(LTR/RTL 等) TTF_SetFontLanguage:设置字体关联的语言 TTF_SetFontScript:设置字体关联的文字脚本(如中文/英文) TTF_SetFontLineSkip:自定义字体行间距 TTF_SetFontWrapAlignment:设置文本换行对齐方式 TTF_SetFontSDF:开启/关闭 SDF(有符号距离场)渲染(适合缩放) 4. 字体回退(Fallback) TTF_AddFallbackFont:添加回退字体(主字体无字形时使用) TTF_RemoveFallbackFont:移除指定回退字体 TTF_ClearFallbackFonts:清空所有回退字体 三、字形(Glyph)操作 TTF_GetGlyphMetrics:获取指定字形的度量信息(宽度、偏移等) TTF_GetGlyphKerning:获取两个字形间的字距调整值 TTF_GetGlyphImage:获取指定字形的渲染图像 TTF_GetGlyphImageForIndex:按字形索引获取渲染图像 TTF_GetGlyphScript:获取字形所属的文字脚本 TTF_RenderGlyph_Solid:渲染单个字形为纯色 Surface TTF_RenderGlyph_Shaded:渲染单个字形为带阴影的 Surface TTF_RenderGlyph_Blended:渲染单个字形为带alpha混合的 Surface TTF_RenderGlyph_LCD:渲染单个字形为 LCD 优化的 Surface 四、文本渲染(基础接口) TTF_RenderText_Solid:渲染文本为纯色 Surface(高性能,无抗锯齿) TTF_RenderText_Shaded:渲染文本为带阴影的 Surface(有抗锯齿) TTF_RenderText_Blended:渲染文本为 alpha 混合 Surface(高质量抗锯齿) TTF_RenderText_LCD:渲染文本为 LCD 优化 Surface(高清显示) TTF_RenderText_Solid_Wrapped:渲染自动换行的纯色文本 TTF_RenderText_Shaded_Wrapped:渲染自动换行的带阴影文本 TTF_RenderText_Blended_Wrapped:渲染自动换行的 alpha 混合文本 TTF_RenderText_LCD_Wrapped:渲染自动换行的 LCD 优化文本 TTF_MeasureString:测量文本渲染后的尺寸(不实际渲染) TTF_GetStringSize:获取文本的宽高尺寸 TTF_GetStringSizeWrapped:获取自动换行文本的宽高尺寸 五、文本引擎(TextEngine)(高级渲染) 1. 引擎创建/销毁 TTF_CreateSurfaceTextEngine:创建基于 Surface 的文本引擎(CPU 渲染) TTF_CreateRendererTextEngine:创建基于 SDL_Renderer 的文本引擎(2D 硬件加速) TTF_CreateRendererTextEngineWithProperties:带属性创建 Renderer 文本引擎 TTF_CreateGPUTextEngine:创建基于 GPU 的文本引擎(3D 硬件加速) TTF_CreateGPUTextEngineWithProperties:带属性创建 GPU 文本引擎 TTF_DestroySurfaceTextEngine:销毁 Surface 文本引擎 TTF_DestroyRendererTextEngine:销毁 Renderer 文本引擎 TTF_DestroyGPUTextEngine:销毁 GPU 文本引擎 2. 文本对象(TTF_Text)管理 TTF_CreateText:创建文本对象(绑定字体和文本内容) TTF_DestroyText:销毁文本对象 TTF_SetTextString:设置文本对象的内容 TTF_AppendTextString:追加文本到文本对象 TTF_InsertTextString:插入文本到文本对象 TTF_DeleteTextString:删除文本对象的部分内容 TTF_UpdateText:更新文本对象的渲染数据 TTF_SetTextFont:设置文本对象关联的字体 TTF_SetTextColor:设置文本颜色(8位通道) TTF_SetTextColorFloat:设置文本颜色(浮点通道,0.0-1.0) TTF_SetTextDirection:设置文本排版方向 TTF_SetTextScript:设置文本所属的文字脚本 TTF_SetTextPosition:设置文本渲染位置 TTF_SetTextWrapWidth:设置文本自动换行宽度 TTF_SetTextWrapWhitespaceVisible:设置是否显示换行空白符 TTF_SetTextEngine:为文本对象绑定文本引擎 TTF_GetTextFont:获取文本对象关联的字体 TTF_GetTextColor:获取文本颜色(8位通道) TTF_GetTextColorFloat:获取文本颜色(浮点通道) TTF_GetTextDirection:获取文本排版方向 TTF_GetTextScript:获取文本所属的文字脚本 TTF_GetTextPosition:获取文本渲染位置 TTF_GetTextSize:获取文本渲染后的尺寸 TTF_GetTextWrapWidth:获取文本自动换行宽度 TTF_GetTextEngine:获取文本对象绑定的引擎 3. 高级文本渲染 TTF_DrawSurfaceText:使用 Surface 引擎渲染文本 TTF_DrawRendererText:使用 Renderer 引擎渲染文本 TTF_GetGPUTextDrawData:获取 GPU 文本渲染的绘制数据 TTF_SetGPUTextEngineWinding:设置 GPU 文本引擎的顶点缠绕方向 TTF_GetGPUTextEngineWinding:获取 GPU 文本引擎的顶点缠绕方向 六、文本子串/排版控制 TTF_GetTextSubString:获取文本指定范围的子串 TTF_GetTextSubStringForLine:获取文本指定行的子串 TTF_GetTextSubStringForPoint:获取指定坐标对应的文本子串 TTF_GetTextSubStringsForRange:获取指定范围的所有子串 TTF_GetNextTextSubString:获取下一个文本子串 TTF_GetPreviousTextSubString:获取上一个文本子串 七、常量与枚举 1. 字体样式 TTF_STYLE_NORMAL:正常样式 TTF_STYLE_BOLD:粗体 TTF_STYLE_ITALIC:斜体 TTF_STYLE_UNDERLINE:下划线 TTF_STYLE_STRIKETHROUGH:删除线 2. 字体字重 TTF_FONT_WEIGHT_THIN:极细 TTF_FONT_WEIGHT_LIGHT:细体 TTF_FONT_WEIGHT_NORMAL:常规 TTF_FONT_WEIGHT_MEDIUM:中等 TTF_FONT_WEIGHT_BOLD:粗体 TTF_FONT_WEIGHT_BLACK:黑体 3. 文本方向 TTF_DIRECTION_LTR:从左到右(如英文) TTF_DIRECTION_RTL:从右到左(如阿拉伯语) TTF_DIRECTION_TTB:从上到下(如竖排中文) TTF_DIRECTION_BTT:从下到上 TTF_DIRECTION_INVALID:无效方向 4. 字体提示模式 TTF_HINTING_NONE:无提示(模糊) TTF_HINTING_LIGHT:轻量提示 TTF_HINTING_NORMAL:常规提示 TTF_HINTING_MONO:单色提示(等宽字体优化) 5. 对齐方式 TTF_HORIZONTAL_ALIGN_LEFT:左对齐 TTF_HORIZONTAL_ALIGN_CENTER:居中 TTF_HORIZONTAL_ALIGN_RIGHT:右对齐 6. 图像类型 TTF_IMAGE_SOLID:纯色图像 TTF_IMAGE_SHADED:带阴影图像 TTF_IMAGE_BLENDED:alpha 混合图像 TTF_IMAGE_SDF:SDF 图像 7. 属性常量(PROP) TTF_PROP_FONT_CREATE_SIZE_FLOAT:字体创建时的字号属性 TTF_PROP_FONT_CREATE_DPI_NUMBER:字体创建时的 DPI 属性 TTF_PROP_RENDERER_TEXT_ENGINE_ATLAS_SIZE:渲染引擎纹理图集尺寸 TTF_PROP_GPU_TEXT_ENGINE_DEVICE:GPU 引擎的设备指针属性 八、工具函数 TTF_StringToTag:将字符串转换为 OpenType 标签 TTF_TagToString:将 OpenType 标签转换为字符串 UNICODE_BOM_NATIVE:本地字节序的 Unicode BOM 常量 FreeBASIC 示例代码 ' 引入 SDL 及 SDL_ttf 相关声明(需链接 SDL3 和 SDL3_ttf 库) #Include "SDL.bi" #Include "SDL_ttf.bi" ' 补充关键类型/宏声明(FreeBASIC 绑定可能缺失) #Define TTF_STYLE_BOLD 1 #Define TTF_STYLE_ITALIC 2 #Define TTF_HINTING_NORMAL 2 ' 检查 SDL_ttf 版本 Sub CheckTTFVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【检查 SDL_ttf 版本】") Dim As SDL_version ver TTF_Version(@ver) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_ttf 版本:%d.%d.%d", ver.major, ver.minor, ver.patch) ' 编译期版本检查 #If SDL_TTF_VERSION_ATLEAST(3, 0, 0) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 满足 SDL_ttf 3.0.0 最低版本要求") #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 不满足 SDL_ttf 3.0.0 最低版本要求") #EndIf ' 打印 FreeType 和 HarfBuzz 版本 Dim As SDL_version ftVer, hbVer TTF_GetFreeTypeVersion(@ftVer) TTF_GetHarfBuzzVersion(@hbVer) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "FreeType 版本:%d.%d.%d", ftVer.major, ftVer.minor, ftVer.patch) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "HarfBuzz 版本:%d.%d.%d", hbVer.major, hbVer.minor, hbVer.patch) End Sub ' 基础文本渲染示例(Surface 模式) Sub BasicTextRenderExample(ByVal fontPath As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【基础文本渲染示例】") ' 1. 加载字体(字号 24) Dim As TTF_Font Ptr font = TTF_OpenFont(fontPath, 24) If (font = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载字体失败:%s", TTF_GetError()) Exit Sub End If ' 2. 设置字体样式(粗体+斜体) TTF_SetFontStyle(font, TTF_STYLE_BOLD Or TTF_STYLE_ITALIC) TTF_SetFontHinting(font, TTF_HINTING_NORMAL) ' 开启常规提示 ' 3. 查询字体属性 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "字体家族:%s", TTF_GetFontFamilyName(font)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "字体高度:%d 像素", TTF_GetFontHeight(font)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "行间距:%d 像素", TTF_GetFontLineSkip(font)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "是否等宽:%s", IIf(TTF_FontIsFixedWidth(font), "是", "否")) ' 4. 检查是否包含中文字形 Dim As Uint32 chineseChar = &H4E2D ' "中" 字的 Unicode 编码 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "是否包含 '中' 字形:%s", _ IIf(TTF_FontHasGlyph(font, chineseChar), "是", "否")) ' 5. 渲染文本(Blended 模式,高质量抗锯齿) Dim As SDL_Color textColor = {255, 255, 255, 255} ' 白色 Dim As SDL_Surface Ptr textSurface = TTF_RenderText_Blended(font, "SDL_ttf 文本渲染示例", textColor) If (textSurface = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "渲染文本失败:%s", TTF_GetError()) TTF_CloseFont(font) Exit Sub End If ' 6. 打印文本尺寸 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "文本尺寸:%dx%d 像素", textSurface->w, textSurface->h) ' 7. 保存渲染结果为 PNG(需链接 SDL_image) #If defined(SDL_IMAGE) If (IMG_SavePNG(textSurface, "text_render.png") = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "渲染结果已保存为 text_render.png") End If #EndIf ' 8. 释放资源 SDL_DestroySurface(textSurface) TTF_CloseFont(font) End Sub ' 高级文本引擎示例(Renderer 模式) Sub AdvancedTextEngineExample(ByVal fontPath As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【高级文本引擎示例】") ' 1. 创建窗口和渲染器 Dim As SDL_Window Ptr window = SDL_CreateWindow( _ "SDL_ttf 高级渲染示例", _ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _ 800, 600, _ SDL_WINDOW_SHOWN _ ) If (window = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建窗口失败:%s", SDL_GetError()) Exit Sub End If Dim As SDL_Renderer Ptr renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED Or SDL_RENDERER_PRESENTVSYNC) If (renderer = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建渲染器失败:%s", SDL_GetError()) SDL_DestroyWindow(window) Exit Sub End If ' 2. 创建 Renderer 文本引擎 Dim As TTF_TextEngine Ptr textEngine = TTF_CreateRendererTextEngine(renderer) If (textEngine = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建文本引擎失败:%s", TTF_GetError()) SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) Exit Sub End If ' 3. 加载字体并创建文本对象 Dim As TTF_Font Ptr font = TTF_OpenFont(fontPath, 32) If (font = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载字体失败:%s", TTF_GetError()) TTF_DestroyRendererTextEngine(textEngine) SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) Exit Sub End If Dim As TTF_Text Ptr textObj = TTF_CreateText(font, "SDL_ttf 高级文本引擎示例") If (textObj = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建文本对象失败:%s", TTF_GetError()) TTF_CloseFont(font) TTF_DestroyRendererTextEngine(textEngine) SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) Exit Sub End If ' 4. 设置文本属性 TTF_SetTextColor(textObj, (SDL_Color){0, 255, 255, 255}) ' 青色 TTF_SetTextPosition(textObj, 50, 50) ' 渲染位置 (50,50) TTF_SetTextEngine(textObj, textEngine) ' 绑定文本引擎 ' 5. 渲染循环 Dim As SDL_bool running = SDL_TRUE Dim As SDL_Event evt While (running) ' 事件处理 While (SDL_PollEvent(@evt)) If (evt.type = SDL_QUIT) Then running = SDL_FALSE End If Wend ' 清屏(黑色背景) SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) SDL_RenderClear(renderer) ' 渲染文本 TTF_DrawRendererText(textObj) ' 刷新屏幕 SDL_RenderPresent(renderer) Wend ' 6. 释放资源 TTF_DestroyText(textObj) TTF_CloseFont(font) TTF_DestroyRendererTextEngine(textEngine) SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) End Sub ' 主程序 Sub Main() ' 初始化 SDL 视频子系统 If (SDL_Init(SDL_INIT_VIDEO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 初始化 SDL_ttf If (TTF_Init() = -1) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_ttf 初始化失败:%s", TTF_GetError()) SDL_Quit() Exit Sub End If ' 字体文件路径(替换为实际的字体文件,如 simsun.ttf、arial.ttf) Dim As ZString Ptr fontPath = StrPtr("simsun.ttf") ' 运行示例 CheckTTFVersion() BasicTextRenderExample(fontPath) AdvancedTextEngineExample(fontPath) ' 清理资源 TTF_Quit() SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 SDL_ttf 初始化关键: 必须先调用 SDL_Init(SDL_INIT_VIDEO) 初始化视频子系统,再调用 TTF_Init(); TTF_Init() 内部会加载 FreeType(字体渲染)和 HarfBuzz(文本排版),需确保链接这两个库; 程序退出前必须调用 TTF_Quit(),否则会导致内存泄漏。 字体加载与管理: 支持 TrueType (.ttf)、OpenType (.otf)、WOFF 等主流字体格式; TTF_OpenFontIO 支持从内存流加载字体(适合嵌入资源的游戏/应用); 多语言文本需使用回退字体(TTF_AddFallbackFont),避免部分字形缺失; 字体对象使用后必须调用 TTF_CloseFont 释放,否则会泄漏资源。 文本渲染模式选择: Solid 模式:高性能、无抗锯齿,适合实时更新的文本(如游戏分数); Shaded 模式:带阴影、有抗锯齿,性能中等,适合静态文本; Blended 模式:Alpha 混合、高质量抗锯齿,性能较低,适合UI文本; LCD 模式:针对 LCD 屏幕优化,清晰度最高,仅支持部分字体; 文本引擎模式:硬件加速渲染,适合大量/动态文本(如编辑器、聊天框)。 多语言排版要点: 支持 RTL(从右到左)、TTB(竖排)等排版方向,适配阿拉伯语、日语等; 中文/日文/韩文等CJK文字需使用支持对应字形的字体; TTF_SetFontScript 可指定文字脚本,优化排版规则。 跨平台注意事项: Windows 系统可直接使用系统字体(如 simsun.ttf、microsoftyahei.ttf); Linux 系统需确保安装字体文件,或打包字体到应用目录; macOS 系统字体路径为 /System/Library/Fonts/,如 Arial.ttf; 移动平台需将字体文件放入 assets 目录,使用绝对路径加载。 总结 核心优势: 无缝衔接 SDL 核心库,渲染的文本可直接用于 SDL 窗口/纹理; 支持多渲染模式(CPU/Surface、2D Renderer、3D GPU),兼顾性能与质量; 完整的字体属性控制(样式、字重、间距、描边等),满足各类UI需求; 支持多语言排版(RTL/TTB、CJK字形、回退字体),适配全球市场; 基于成熟的 FreeType/HarfBuzz 库,渲染质量有保障。 使用建议: 静态文本优先使用 Blended 模式,动态文本优先使用 Solid 模式; 大量文本渲染优先使用文本引擎(TextEngine),利用硬件加速; 多语言应用务必添加回退字体,避免字形缺失; 高清显示场景使用 LCD 模式或 SDF 渲染,提升文字清晰度; 字体文件建议打包到应用目录,避免依赖系统字体。 关键点回顾: SDL_ttf 是 SDL 的字体渲染扩展库,核心依赖 FreeType 和 HarfBuzz; TTF_Init()/TTF_Quit() 是必选的初始化/清理接口; TTF_Font 是字体对象核心,支持样式、字重、间距等属性配置; 文本渲染分基础模式(Solid/Shaded/Blended)和高级引擎模式(Surface/Renderer/GPU); 多语言排版需关注文本方向(LTR/RTL)、回退字体和字形检查。
      • 2026年-3月-7日
      • 3 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_SDL_image 核心 API 集合(CategoryAPI) 2026-3-7
      SDL3_API分类参考_SDL_image 核心 API 集合(CategoryAPI) SDL_image 核心 API 集合(CategoryAPI) SDL_image 是 SDL 的官方图像扩展库,该分类汇总了 SDL_image 所有核心 API,涵盖静态图像加载/保存、动画解码/编码、格式检测、GPU 纹理加载等全量功能,是 SDL 生态中处理图像的核心接口集合。 核心 API 列表(按功能分类) 一、动画编解码核心接口 1. 动画解码器(AnimationDecoder) IMG_CreateAnimationDecoder:创建动画解码器实例(通用接口) IMG_CreateAnimationDecoder_IO:从 SDL_IOStream 流创建动画解码器 IMG_CreateAnimationDecoderWithProperties:带自定义属性创建动画解码器(如 GIF 颜色数、AVIF 线程数) IMG_CloseAnimationDecoder:关闭并释放动画解码器资源 IMG_GetAnimationDecoderFrame:获取解码器指定索引的帧数据 IMG_GetNextAnimationDecoderFrame:获取解码器下一帧数据(逐帧播放) IMG_GetAnimationDecoderMetadata:获取动画元数据(帧数、循环次数等) IMG_GetAnimationDecoderPresentationTimestampMS:获取帧的展示时间戳(毫秒) IMG_GetAnimationDecoderProperties:获取解码器的配置属性 IMG_GetAnimationDecoderStatus:获取解码器当前状态(成功/失败/完成等) IMG_ResetAnimationDecoder:重置动画解码器到初始状态 2. 动画编码器(AnimationEncoder) IMG_CreateAnimationEncoder:创建动画编码器实例(通用接口) IMG_CreateAnimationEncoder_IO:从 SDL_IOStream 流创建动画编码器 IMG_CreateAnimationEncoderWithProperties:带自定义属性创建动画编码器(如质量、关键帧间隔) IMG_CloseAnimationEncoder:关闭并释放动画编码器资源 IMG_AddAnimationEncoderFrame:向编码器添加单帧数据(用于生成动画) 3. 动画流(AnimationStream) IMG_CreateAnimationStream:创建动画流实例(实时编解码) IMG_CreateAnimationStream_IO:从 SDL_IOStream 流创建动画流 IMG_CreateAnimationStreamWithProperties:带自定义属性创建动画流 IMG_CloseAnimationStream:关闭并释放动画流资源 4. 动画数据结构与工具 IMG_Animation:动画数据结构体(包含所有帧、时长、循环等信息) IMG_LoadAnimation:从文件加载完整动画数据(如 GIF/APNG/WEBP) IMG_LoadAnimation_IO:从 SDL_IOStream 流加载动画 IMG_LoadAnimationTyped_IO:指定格式从流加载动画(避免自动检测) IMG_FreeAnimation:释放 IMG_Animation 结构体资源 IMG_SaveAnimation:将动画数据保存为文件 IMG_SaveAnimationTyped_IO:指定格式将动画保存到 SDL_IOStream 流 5. 动画解码器状态枚举 IMG_DECODER_STATUS_OK:解码器状态正常(可继续解码) IMG_DECODER_STATUS_COMPLETE:解码完成(所有帧已处理) IMG_DECODER_STATUS_FAILED:解码失败(数据错误/格式不支持) IMG_DECODER_STATUS_INVALID:解码器实例无效(未初始化/已释放) 二、静态图像加载/保存 1. 通用加载接口 IMG_Load:从文件加载图像为 SDL_Surface(自动检测格式) IMG_Load_IO:从 SDL_IOStream 流加载图像为 SDL_Surface IMG_LoadTyped_IO:指定格式从流加载图像(如强制按 PNG 解析) IMG_LoadTexture:从文件加载图像为 SDL_Texture(GPU 纹理,需 SDL_Renderer) IMG_LoadTexture_IO:从流加载图像为 SDL_Texture IMG_LoadTextureTyped_IO:指定格式从流加载为 SDL_Texture IMG_LoadGPUTexture:加载图像为 GPU 原生纹理(如 Vulkan/D3D 纹理) IMG_LoadGPUTexture_IO:从流加载为 GPU 原生纹理 2. 格式专属加载接口 IMG_LoadBMP_IO/IMG_LoadPNG_IO/IMG_LoadJPG_IO:BMP/PNG/JPG 格式专属加载 IMG_LoadGIF_IO/IMG_LoadWEBP_IO/IMG_LoadAVIF_IO:GIF/WEBP/AVIF 格式专属加载 IMG_LoadICO_IO/IMG_LoadCUR_IO:图标/光标格式加载 IMG_LoadSVG_IO/IMG_LoadSizedSVG_IO:SVG 矢量图加载(支持指定尺寸) IMG_LoadXPM_IO/IMG_ReadXPMFromArray:XPM 格式加载(支持内存数组) IMG_LoadANIAnimation_IO/IMG_LoadGIFAnimation_IO:ANI/GIF 动画专属加载 IMG_LoadAPNGAnimation_IO/IMG_LoadWEBPAnimation_IO:APNG/WEBP 动画专属加载 3. 图像保存接口 IMG_Save:将 SDL_Surface 保存为图像文件(自动检测格式) IMG_SaveTyped_IO:指定格式将图像保存到 SDL_IOStream 流 IMG_SaveBMP/IMG_SavePNG/IMG_SaveJPG:BMP/PNG/JPG 格式专属保存 IMG_SaveGIF/IMG_SaveWEBP/IMG_SaveAVIF:GIF/WEBP/AVIF 格式专属保存 IMG_SaveICO/IMG_SaveCUR:图标/光标格式保存 IMG_SaveANIAnimation_IO/IMG_SaveGIFAnimation_IO:ANI/GIF 动画专属保存 IMG_SaveAPNGAnimation_IO/IMG_SaveWEBPAnimation_IO:APNG/WEBP 动画专属保存 三、格式检测接口 IMG_isBMP/IMG_isPNG/IMG_isJPG:检测数据是否为 BMP/PNG/JPG 格式 IMG_isGIF/IMG_isAVIF/IMG_isWEBP:检测数据是否为 GIF/AVIF/WEBP 格式 IMG_isICO/IMG_isCUR/IMG_isANI:检测数据是否为 ICO/CUR/ANI 格式 IMG_isSVG/IMG_isTIF/IMG_isXPM:检测数据是否为 SVG/TIF/XPM 格式 IMG_isLBM/IMG_isPCX/IMG_isPNM:检测数据是否为 LBM/PCX/PNM 格式 IMG_isQOI/IMG_isXCF/IMG_isXV:检测数据是否为 QOI/XCF/XV 格式 IMG_isJXL:检测数据是否为 JXL(JPEG XL)格式 四、特殊功能接口 IMG_CreateAnimatedCursor:从动画数据创建系统动画光标 IMG_GetClipboardImage:获取剪贴板中的图像数据(SDL_Surface) IMG_ReadXPMFromArrayToRGB888:从 XPM 数组加载为 RGB888 格式图像 五、属性常量(编解码配置) 1. 解码器属性 IMG_PROP_ANIMATION_DECODER_CREATE_FILENAME_STRING:解码器关联的文件名属性 IMG_PROP_ANIMATION_DECODER_CREATE_TYPE_STRING:解码器目标格式(如 "gif"/"avif") IMG_PROP_ANIMATION_DECODER_CREATE_GIF_NUM_COLORS_NUMBER:GIF 解码颜色数限制 IMG_PROP_ANIMATION_DECODER_CREATE_AVIF_MAX_THREADS_NUMBER:AVIF 解码最大线程数 IMG_PROP_ANIMATION_DECODER_METADATA_FRAME_COUNT_NUMBER:动画帧数元数据 IMG_PROP_ANIMATION_DECODER_METADATA_LOOP_COUNT_NUMBER:动画循环次数元数据 2. 编码器属性 IMG_PROP_ANIMATION_ENCODER_CREATE_QUALITY_NUMBER:编码质量(0-100) IMG_PROP_ANIMATION_ENCODER_CREATE_TYPE_STRING:编码器目标格式 IMG_PROP_ANIMATION_ENCODER_CREATE_AVIF_KEYFRAME_INTERVAL_NUMBER:AVIF 关键帧间隔 IMG_PROP_ANIMATION_ENCODER_CREATE_GIF_USE_LUT_BOOLEAN:GIF 编码是否使用颜色查找表 3. 通用属性 IMG_PROP_METADATA_AUTHOR_STRING:图像作者元数据 IMG_PROP_METADATA_COPYRIGHT_STRING:图像版权元数据 IMG_PROP_METADATA_TITLE_STRING:图像标题元数据 IMG_PROP_ANIMATION_STREAM_CREATE_QUALITY_NUMBER:动画流编码质量 六、版本相关宏/函数 IMG_Version:获取当前 SDL_image 库的版本信息 SDL_IMAGE_MAJOR_VERSION:SDL_image 主版本号宏(如 3 代表 SDL_image 3.x) SDL_IMAGE_VERSION:构造版本结构体的宏 SDL_IMAGE_VERSION_ATLEAST:编译期检查 SDL_image 版本是否满足最低要求 FreeBASIC 示例代码 ' 引入 SDL 及 SDL_image 相关声明(需链接 SDL3 和 SDL3_image 库) #Include "SDL.bi" #Include "SDL_image.bi" ' 补充关键类型/宏声明(FreeBASIC 绑定可能缺失) Type IMG_Animation ' 简化版动画结构体(完整定义需参考 SDL_image 源码) frames As SDL_Surface Ptr Ptr ' 帧数据数组 delays As Integer Ptr ' 每帧延迟(毫秒) count As Integer ' 总帧数 loops As Integer ' 循环次数(0=无限) End Type Declare Function IMG_LoadAnimation CDecl (ByVal file As ZString Ptr) As IMG_Animation Ptr Declare Sub IMG_FreeAnimation CDecl (ByVal anim As IMG_Animation Ptr) Declare Function IMG_isGIF CDecl (ByVal src As Const Any Ptr, ByVal len As Size_t) As SDL_bool Declare Function IMG_SavePNG CDecl (ByVal surface As SDL_Surface Ptr, ByVal file As ZString Ptr) As SDL_bool ' 检查 SDL_image 版本 Sub CheckImageVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【检查 SDL_image 版本】") Dim As SDL_version ver IMG_Version(@ver) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_image 版本:%d.%d.%d", ver.major, ver.minor, ver.patch) ' 编译期版本检查示例 #If SDL_IMAGE_VERSION_ATLEAST(3, 0, 0) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 满足 SDL_image 3.0.0 最低版本要求") #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 不满足 SDL_image 3.0.0 最低版本要求") #EndIf End Sub ' 加载并显示静态图像(PNG/JPG) Sub LoadStaticImageExample(ByVal filename As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【加载静态图像:%s】", filename) ' 加载图像为 SDL_Surface Dim As SDL_Surface Ptr surface = IMG_Load(filename) If (surface = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载失败:%s", SDL_GetError()) Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "图像信息:%dx%d 像素,%d 位深", _ surface->w, surface->h, surface->format->BitsPerPixel) ' 保存为 PNG 格式(格式转换示例) Dim As ZString * 256 savePath SDL_snprintf(@savePath, sizeof(savePath), "saved_%s.png", SDL_GetBasename(filename)) If (IMG_SavePNG(surface, @savePath) = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "已保存为:%s", savePath) End If ' 释放资源 SDL_DestroySurface(surface) End Sub ' 加载并解析 GIF 动画 Sub LoadGifAnimationExample(ByVal filename As ZString Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【加载 GIF 动画:%s】", filename) ' 1. 检测文件是否为 GIF 格式 Dim As SDL_RWops Ptr rw = SDL_RWFromFile(filename, "rb") If (rw = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "打开文件失败:%s", SDL_GetError()) Exit Sub End If ' 读取文件头用于格式检测 Dim As UByte header(0 To 3) SDL_RWread(rw, @header(0), 1, 4) SDL_RWseek(rw, 0, RW_SEEK_SET) ' 重置文件指针 If (IMG_isGIF(@header(0), 4) = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 检测为 GIF 格式文件") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 非 GIF 格式文件") SDL_RWclose(rw) Exit Sub End If SDL_RWclose(rw) ' 2. 加载 GIF 动画数据 Dim As IMG_Animation Ptr anim = IMG_LoadAnimation(filename) If (anim = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载动画失败:%s", SDL_GetError()) Exit Sub End If ' 3. 解析动画信息 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "动画总帧数:%d", anim->count) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "循环次数:%s", IIf(anim->loops=0, "无限", Str(anim->loops))) ' 打印每帧延迟 For i As Integer = 0 To anim->count - 1 If (anim->frames[i] <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "帧 %d:%dx%d 像素,延迟 %d 毫秒", _ i, anim->frames[i]->w, anim->frames[i]->h, anim->delays[i]) End If Next ' 4. 释放动画资源 IMG_FreeAnimation(anim) End Sub ' 主程序 Sub Main() ' 初始化 SDL 视频子系统(加载图像需要) If (SDL_Init(SDL_INIT_VIDEO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 初始化 SDL_image(加载所有支持的格式) Dim As Integer flags = IMG_INIT_PNG Or IMG_INIT_JPG Or IMG_INIT_GIF Or IMG_INIT_WEBP If (IMG_Init(flags) <> flags) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_image 初始化失败:%s", IMG_GetError()) SDL_Quit() Exit Sub End If ' 运行示例 CheckImageVersion() LoadStaticImageExample(StrPtr("test.png")) ' 替换为实际的图像文件路径 LoadGifAnimationExample(StrPtr("test.gif")) ' 替换为实际的 GIF 文件路径 ' 清理资源 IMG_Quit() SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 SDL_image 初始化与清理: 必须调用 IMG_Init() 初始化并指定支持的格式(如 IMG_INIT_PNG/IMG_INIT_GIF),未指定的格式无法加载; 初始化标志需与返回值对比,确认所有格式都成功初始化; 程序退出前必须调用 IMG_Quit() 释放 SDL_image 资源。 动画处理关键要点: IMG_Animation 是动画的核心数据结构,包含所有帧的 SDL_Surface、每帧延迟、循环次数; 加载 GIF/APNG 等动画时,优先使用 IMG_LoadAnimation,而非普通的 IMG_Load(后者仅加载第一帧); 动画帧的延迟单位为毫秒,需结合 SDL_Delay() 实现逐帧播放。 格式检测规则: IMG_isXXX() 函数仅需传入文件头前几个字节(通常 4-8 字节)即可检测格式; 检测前需确保数据指针有效,且长度不小于格式标识的最小长度; 推荐先检测格式再加载,可提前过滤不支持的文件。 IOStream 接口优势: _IO 后缀的接口支持从内存流/网络流加载图像,无需写入本地文件; 使用 SDL_IOStream 时可通过 IMG_PROP_*_IOSTREAM_AUTOCLOSE 属性控制流的自动关闭; 适合处理加密/压缩的图像数据(先解密/解压到内存流,再加载)。 跨平台注意事项: SVG 加载依赖系统的 SVG 解析库(如 librsvg),部分平台需额外链接; AVIF/WEBP 等现代格式需确保 SDL_image 编译时启用了对应编解码器; 移动平台需注意文件路径格式(如 Android 的 assets 目录需用 SDL_RWFromFile 配合绝对路径)。 总结 核心优势: 一站式支持数十种图像格式,无需单独集成各格式的编解码库; 无缝衔接 SDL 核心库,加载的图像可直接用于 SDL 渲染/显示; 支持动画编解码、GPU 纹理加载等高级功能,满足游戏/多媒体开发需求; 跨平台接口统一,无需适配不同系统的图像处理逻辑。 使用建议: 初始化时仅指定实际需要的格式标志(减少库体积和内存占用); 加载大图像/动画时优先使用 IOStream 接口,避免内存峰值; 动画播放需注意帧延迟的累积,避免播放速度不一致; 保存图像时指定格式专属接口(如 IMG_SavePNG),比通用 IMG_Save 更稳定。 关键点回顾: SDL_image 是 SDL 的图像扩展库,核心功能包括静态图像加载/保存、动画编解码、格式检测; IMG_Init()/IMG_Quit() 是初始化/清理的必选接口,需指定支持的格式标志; IMG_Animation 结构体封装动画全量数据,IMG_LoadAnimation 用于加载GIF/APNG等动画; _IO 后缀接口支持流操作,适合内存/网络图像处理,_Typed_IO 接口可强制指定格式解析。
      • 2026年-3月-7日
      • 4 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_其它功能(CategoryMisc) 2026-3-7
      SDL3_API分类参考_其它功能(CategoryMisc) 其它功能子系统(CategoryMisc) SDL 中无法归类到其他特定子系统的零散 API 函数集合,这类函数功能独立且不隶属于某一核心模块,目前仅包含 URL 打开这一通用功能。 函数 SDL_OpenURL:调用系统默认程序打开指定的 URL(支持 http/https 网页链接、mailto 邮件链接、file 本地文件链接等),跨平台行为一致,无需关心不同系统的 URL 打开方式差异 数据类型 (无) 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充 SDL_OpenURL 函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_OpenURL CDecl (ByVal url As ZString Ptr) As SDL_bool ' 辅助函数:封装 URL 打开逻辑并处理错误 Function OpenURLHelper(ByVal url As ZString Ptr, ByVal desc As ZString Ptr) As SDL_bool SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "尝试打开 %s:%s", desc, url) ' 调用 SDL_OpenURL 打开 URL Dim As SDL_bool result = SDL_OpenURL(url) ' 处理返回结果 If (result = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ %s 打开成功", desc) Return SDL_TRUE Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ %s 打开失败:%s", desc, SDL_GetError()) Return SDL_FALSE End If End Function ' ==================== 示例 1:打开网页链接 ==================== Sub OpenWebURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例 1:打开网页链接】") ' 打开 SDL 官方网站 OpenURLHelper(StrPtr("https://www.libsdl.org/"), StrPtr("SDL 官方网站")) ' 打开带参数的网页链接(如搜索页面) OpenURLHelper(StrPtr("https://www.google.com/search?q=SDL+OpenURL"), StrPtr("Google 搜索页面")) End Sub ' ==================== 示例 2:打开邮件链接 ==================== Sub OpenMailURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 2:打开邮件链接】") ' 打开系统默认邮件客户端,预填收件人、主题、正文 Dim As ZString * 256 mailURL SDL_snprintf( _ @mailURL, _ sizeof(mailURL), _ "mailto:support@example.com?subject=SDL 反馈&body=我在使用 SDL_OpenURL 时遇到了以下问题:" _ ) OpenURLHelper(@mailURL, StrPtr("邮件链接")) End Sub ' ==================== 示例 3:打开本地文件/文件夹 ==================== Sub OpenLocalFileURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 3:打开本地文件/文件夹】") ' 注意:本地文件需使用 file:// 协议,且路径格式需适配平台 #If Defined(SDL_PLATFORM_WINDOWS) ' Windows 路径示例(需转义反斜杠,或使用正斜杠) Dim As ZString Ptr folderURL = StrPtr("file:///C:/Users/Public/Documents") OpenURLHelper(folderURL, StrPtr("Windows 公共文档文件夹")) #ElseIf Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS 路径示例 Dim As ZString Ptr folderURL = StrPtr("file:///home/user/Documents") OpenURLHelper(folderURL, StrPtr("Linux 文档文件夹")) #EndIf End Sub ' ==================== 示例 4:处理无效 URL ==================== Sub OpenInvalidURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 4:处理无效 URL】") ' 无效的 URL(无协议头) OpenURLHelper(StrPtr("www.example.com"), StrPtr("无效 URL(无协议头)")) ' 不存在的本地文件 OpenURLHelper(StrPtr("file:///不存在的文件路径.txt"), StrPtr("不存在的本地文件")) End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(Misc 子系统无需特定初始化,基础初始化即可) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 OpenWebURLExample() OpenMailURLExample() OpenLocalFileURLExample() OpenInvalidURLExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 URL 格式规范: SDL_OpenURL 支持标准 RFC 3986 格式的 URL,必须包含协议头(如 http://、mailto:、file://),无协议头的字符串会被判定为无效 URL; 特殊字符(如空格、中文、问号)需进行 URL 编码(如空格替换为 %20,中文转换为 UTF-8 编码的十六进制值); 本地文件路径需使用 file:// 协议,Windows 路径需注意斜杠方向(推荐使用正斜杠 /,避免反斜杠 \ 的转义问题)。 跨平台实现逻辑: 平台 底层实现方式 特殊说明 Windows ShellExecuteW 函数 需要 URL 转换为宽字符格式 macOS NSWorkspace 的 openURL 方法 需在主线程调用,否则可能无响应 Linux xdg-open 命令(桌面环境) 依赖桌面环境的默认程序配置 Android Intent.ACTION_VIEW 意图 需申请 INTERNET 权限(网页链接) iOS UIApplication 的 openURL 方法 需配置 ATS 规则(http 链接) 错误处理要点: SDL_OpenURL 返回 SDL_TRUE 仅表示「成功发起打开请求」,不代表 URL 本身有效或程序能正常打开; 返回 SDL_FALSE 时,可通过 SDL_GetError() 获取具体错误信息(如「无效的 URL 格式」「无默认程序关联」); 本地文件 URL 失败常见原因:文件不存在、权限不足、无默认文件管理器。 使用限制: 移动平台(Android/iOS)打开 URL 可能触发应用跳转,需处理应用生命周期变化; macOS/Linux 下打开 URL 可能需要应用有桌面权限(沙箱环境下需配置); 避免在子线程中频繁调用 SDL_OpenURL,部分平台(如 macOS)要求主线程调用。 总结 核心优势: 跨平台统一的 URL 打开接口,无需针对不同系统编写原生代码; 自动适配系统默认程序,符合用户使用习惯; 简单的返回值和错误信息,便于错误处理。 使用建议: 调用前确保 URL 格式正确(含协议头、特殊字符编码); 对返回结果进行判断,失败时给出用户友好提示; 本地文件 URL 需做平台适配,避免路径格式错误; 移动平台调用后需处理应用切换/返回的逻辑。 关键点回顾: CategoryMisc 是 SDL 的杂项函数集合,目前仅包含 SDL_OpenURL 一个核心函数; SDL_OpenURL 可打开网页、邮件、本地文件等各类标准 URL,跨平台行为一致; URL 必须包含协议头,特殊字符需编码,本地文件需使用 file:// 协议; 返回值仅表示请求发起结果,需结合 SDL_GetError() 排查失败原因。
      • 2026年-3月-7日
      • 5 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_GUID 处理(CategoryGUID) 2026-3-7
      SDL3_API分类参考_GUID 处理(CategoryGUID) GUID 处理子系统(CategoryGUID) GUID(全局唯一标识符)是一个 128 位的数值,用于唯一标识某个对象/实体——其核心特性是「全局唯一性」,可确保在不同系统、不同场景下不会出现重复值。 SDL 为 GUID 提供了核心的序列化/反序列化能力:支持将二进制格式的 GUID 转换为人类可读的字符串格式,也支持将字符串格式的 GUID 解析回二进制结构,方便存储、传输和展示。 函数 SDL_GUIDToString:将二进制格式的 SDL_GUID 结构体转换为字符串格式(输出如 "12345678-1234-1234-1234-1234567890ab"),参数需指定输出缓冲区大小以避免溢出 SDL_StringToGUID:将字符串格式的 GUID(标准 UUID 格式)解析为二进制的 SDL_GUID 结构体,解析失败时返回全零的 GUID 数据类型 (无) 结构体 SDL_GUID:存储 128 位 GUID 的二进制结构体,内部包含一个 16 字节的数组(对应 128 位),是 SDL 中表示 GUID 的核心数据结构 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充 SDL_GUID 结构体和函数声明(FreeBASIC 绑定可能缺失) Type SDL_GUID data(0 To 15) As Uint8 ' 16字节 = 128位,存储GUID的二进制数据 End Type ' GUID字符串的标准长度:36个可见字符 + 1个终止符 = 37 Const SDL_GUID_STRING_LENGTH = 37 Declare Sub SDL_GUIDToString CDecl ( _ ByVal guid As SDL_GUID, _ ByVal str As ZString Ptr, _ ByVal maxlen As Size_t _ ) Declare Function SDL_StringToGUID CDecl ( _ ByVal str As ZString Ptr _ ) As SDL_GUID ' 辅助函数:打印二进制 GUID 数据 Sub PrintGUIDBinary(ByVal guid As SDL_GUID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "GUID 二进制数据(16字节):") For i As Integer = 0 To 15 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 字节 %2d: 0x%02X", i, guid.data(i)) ' 每4字节换行,方便阅读 If ((i + 1) Mod 4 = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "") End If Next End Sub ' 辅助函数:比较两个 GUID 是否相等 Function GUIDEquals(ByVal a As SDL_GUID, ByVal b As SDL_GUID) As SDL_bool For i As Integer = 0 To 15 If (a.data(i) <> b.data(i)) Then Return SDL_FALSE End If Next Return SDL_TRUE End Function ' ==================== 示例 1:GUID 转字符串 ==================== Sub GUIDToStringExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例 1:GUID 转字符串】") ' 构造一个测试用的 GUID(二进制数据) Dim As SDL_GUID testGUID ' 手动填充测试数据(模拟一个真实的 GUID 二进制值) testGUID.data(0) = &H12 : testGUID.data(1) = &H34 : testGUID.data(2) = &H56 : testGUID.data(3) = &H78 testGUID.data(4) = &H90 : testGUID.data(5) = &HAB : testGUID.data(6) = &HCD : testGUID.data(7) = &HEF testGUID.data(8) = &H11 : testGUID.data(9) = &H22 : testGUID.data(10) = &H33 : testGUID.data(11) = &H44 testGUID.data(12) = &H55 : testGUID.data(13) = &H66 : testGUID.data(14) = &H77 : testGUID.data(15) = &H88 ' 打印二进制 GUID PrintGUIDBinary(testGUID) ' 转换为字符串格式 Dim As ZString * SDL_GUID_STRING_LENGTH guidStr SDL_GUIDToString(testGUID, @guidStr, sizeof(guidStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "GUID 转换为字符串:%s", guidStr) End Sub ' ==================== 示例 2:字符串转 GUID ==================== Sub StringToGUIDExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 2:字符串转 GUID】") ' 标准格式的 GUID 字符串(UUID 格式) Dim As ZString Ptr guidStr = StrPtr("12345678-90ab-cdef-1122-334455667788") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "待解析的 GUID 字符串:%s", guidStr) ' 将字符串解析为二进制 GUID Dim As SDL_GUID parsedGUID = SDL_StringToGUID(guidStr) ' 打印解析后的二进制数据 PrintGUIDBinary(parsedGUID) ' 验证解析结果:转换回字符串,检查是否与原字符串一致 Dim As ZString * SDL_GUID_STRING_LENGTH checkStr SDL_GUIDToString(parsedGUID, @checkStr, sizeof(checkStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析后转回字符串:%s", checkStr) If (SDL_strcmp(guidStr, @checkStr) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 解析与转换结果一致") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 解析与转换结果不一致") End If End Sub ' ==================== 示例 3:无效 GUID 字符串处理 ==================== Sub InvalidGUIDStringExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 3:无效 GUID 字符串处理】") ' 无效的 GUID 字符串(长度不足、格式错误) Dim As ZString Ptr invalidStrs(2) = { _ StrPtr("12345678-90ab-cdef-1122"), ' 长度不足 StrPtr("12345678-90ab-cdef-1122-zzzzzzzzzzzz"), ' 包含非十六进制字符 StrPtr("无效的GUID字符串") ' 完全错误格式 } ' 全零 GUID(用于对比解析失败的情况) Dim As SDL_GUID zeroGUID For i As Integer = 0 To 15 zeroGUID.data(i) = 0 Next For i As Integer = 0 To 2 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析无效字符串:%s", invalidStrs(i)) Dim As SDL_GUID parsedGUID = SDL_StringToGUID(invalidStrs(i)) If (GUIDEquals(parsedGUID, zeroGUID) = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " → 解析失败,返回全零 GUID") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " → 解析结果非全零(意外情况)") End If Next End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(GUID 子系统无需特定初始化) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 GUIDToStringExample() StringToGUIDExample() InvalidGUIDStringExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 GUID 格式规范: SDL 遵循标准 UUID v4 格式:8-4-4-4-12 共 36 个字符(含 4 个连字符),例如 12345678-1234-1234-1234-1234567890ab; 二进制存储为 16 字节(128 位),字符串格式是其十六进制的可读性表示; SDL_GUIDToString 的输出缓冲区至少需要 37 字节(36 个字符 + 1 个字符串终止符 \0)。 解析/转换规则: SDL_StringToGUID 仅支持标准 UUID 格式的字符串,非标准格式(如无连字符、大小写混合、非十六进制字符)会解析失败; 解析失败时返回全零的 SDL_GUID(所有 16 字节均为 0),可通过对比全零 GUID 判断解析是否成功; SDL_GUIDToString 输出的字符串为小写形式,输入字符串为大写时也可正常解析(大小写不敏感)。 典型使用场景: 标识游戏控制器/输入设备(SDL 中常用于区分不同的物理设备); 生成唯一的用户/设备 ID 用于数据存储/传输; 跨平台唯一标识资源(如配置文件、缓存数据)。 跨平台注意事项: SDL_GUID 结构体的二进制布局在所有平台一致,可安全序列化/反序列化; 字符串格式的 GUID 无平台差异,是跨平台传输的首选格式; 避免手动修改 SDL_GUID 的二进制数据,如需生成新 GUID,需使用平台原生的 GUID 生成函数(如 Windows 的 CoCreateGuid)。 总结 核心优势: 提供简单统一的 GUID 序列化/反序列化接口,无需手动处理二进制与字符串的转换; 严格遵循标准 UUID 格式,保证与其他系统/库的兼容性; 解析失败时返回可预测的全零 GUID,便于错误处理。 使用建议: 转换字符串时,务必使用 SDL_GUID_STRING_LENGTH(37)作为缓冲区大小,避免溢出; 解析字符串后,先对比全零 GUID 判断是否解析成功,再进行后续操作; 存储 GUID 时优先选择字符串格式(易读、易调试),传输/存储体积敏感时使用二进制格式。 关键点回顾: SDL_GUID 是 16 字节的结构体,用于存储 128 位的全局唯一标识符; SDL_GUIDToString/SDL_StringToGUID 实现 GUID 二进制与字符串的双向转换; 解析无效字符串时返回全零 GUID,可通过对比全零值判断解析结果; 字符串格式遵循标准 UUID 格式(36 字符 + 终止符),缓冲区需至少 37 字节。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_标准工具函数(CategoryStdinc) 2026-3-7
      SDL3_API分类参考_标准工具函数(CategoryStdinc) 标准工具函数子系统(CategoryStdinc) SDL 提供了一套自研的核心 C 运行时函数实现,旨在解决跨平台开发中 C 标准库的兼容性问题: 解耦运行时依赖:应用可直接使用这些函数,无需依赖特定的 C 运行时库(甚至无需任何 C 运行时); 跨平台行为一致:避免不同平台的 C 函数表现差异(如 Windows/Linux 下 snprintf() 行为不同、itoa() 仅存在于部分平台); 性能与兼容性兼顾:对于 SDL_memcpy 等高频函数,SDL 会在底层调用平台原生实现(若其更高效且稳定),既减少库体积又保证性能; 扩展增强功能:补充了 C 标准未定义但实用的功能(如 SDL_crc32 校验、SDL_strlcpy 安全字符串拷贝)。 函数 1. 内存管理函数 SDL_malloc:内存分配(替代标准 malloc,跨平台行为一致) SDL_calloc:分配并清零内存(替代标准 calloc) SDL_realloc:内存重分配(替代标准 realloc) SDL_free:释放内存(替代标准 free,需与 SDL 分配函数配对使用) SDL_aligned_alloc:按指定对齐方式分配内存(如 16 字节对齐) SDL_aligned_free:释放对齐分配的内存 SDL_GetNumAllocations:获取当前 SDL 分配的内存块数量(调试内存泄漏) SDL_GetMemoryFunctions:获取当前使用的内存分配函数指针 SDL_SetMemoryFunctions:自定义 SDL 的内存分配函数(如接入自定义内存池) SDL_GetOriginalMemoryFunctions:获取 SDL 原生的内存函数指针 2. 字符串操作函数 SDL_strlen:计算字符串长度(替代 strlen,仅统计 ASCII 字符) SDL_utf8strlen:计算 UTF-8 字符串的字符数(而非字节数) SDL_strlcpy:安全字符串拷贝(防止缓冲区溢出,替代 strcpy) SDL_strlcat:安全字符串拼接(替代 strcat) SDL_strcmp/SDL_strncmp:字符串比较(区分大小写) SDL_strcasecmp/SDL_strncasecmp:字符串比较(不区分大小写) SDL_strchr/SDL_strrchr:查找字符在字符串中的位置 SDL_strstr/SDL_strnstr:查找子字符串 SDL_strdup/SDL_strndup:字符串拷贝(自动分配内存) SDL_strtok_r:可重入的字符串分割(替代 strtok,线程安全) SDL_itoa/SDL_ltoa/SDL_lltoa:整数转字符串(跨平台兼容,标准库无统一实现) SDL_uitoa/SDL_ultoa/SDL_ulltoa:无符号整数转字符串 SDL_atof/SDL_atoi:字符串转数值(替代 atof/atoi) SDL_strtod/SDL_strtol/SDL_strtoll:字符串转数值(带错误处理) SDL_strtoul/SDL_strtoull:字符串转无符号数值 SDL_asprintf/SDL_vasprintf:动态格式化字符串(自动分配内存) SDL_snprintf/SDL_vsnprintf:安全格式化字符串(防止缓冲区溢出) SDL_utf8strlcpy:UTF-8 安全字符串拷贝 3. 内存操作函数 SDL_memcpy:内存拷贝(替代 memcpy,平台优化实现) SDL_memmove:内存移动(处理重叠内存区域,替代 memmove) SDL_memset:内存填充(替代 memset) SDL_memset4:按 4 字节单位填充内存(更高效) SDL_memcmp:内存比较(替代 memcmp) 4. 数学函数 SDL_abs:整数绝对值(替代 abs) SDL_fabs/SDL_fabsf:浮点数绝对值(替代 fabs/fabsf) SDL_sin/SDL_sinf/SDL_cos/SDL_cosf:三角函数(正弦/余弦) SDL_atan/SDL_atanf/SDL_atan2/SDL_atan2f:反正切函数 SDL_acos/SDL_acosf/SDL_asin/SDL_asinf:反余弦/反正弦函数 SDL_tan/SDL_tanf:正切函数 SDL_sqrt/SDL_sqrtf:平方根函数 SDL_pow/SDL_powf:幂函数 SDL_exp/SDL_expf:指数函数 SDL_log/SDL_logf/SDL_log10/SDL_log10f:对数函数 SDL_floor/SDL_floorf:向下取整 SDL_ceil/SDL_ceilf:向上取整 SDL_round/SDL_roundf:四舍五入 SDL_trunc/SDL_truncf:截断小数部分 SDL_lround/SDL_lroundf:四舍五入转长整数 SDL_fmod/SDL_fmodf:取模运算(浮点数) SDL_copysign/SDL_copysignf:复制符号位 SDL_isinf/SDL_isinff:检测无穷大 SDL_isnan/SDL_isnanf:检测非数值(NaN) SDL_PI_F/SDL_PI_D:圆周率常量(单/双精度) 5. 字符判断函数 SDL_isalpha/SDL_isdigit/SDL_isalnum:字母/数字/字母数字判断 SDL_islower/SDL_isupper:大小写字母判断 SDL_isspace/SDL_isblank:空白字符判断 SDL_iscntrl/SDL_isprint/SDL_isgraph:控制字符/可打印字符/图形字符判断 SDL_ispunct:标点符号判断 SDL_isxdigit:十六进制字符判断 SDL_tolower/SDL_toupper:字符大小写转换 6. 排序/查找函数 SDL_qsort/SDL_qsort_r:快速排序(qsort_r 为可重入版本,线程安全) SDL_bsearch/SDL_bsearch_r:二分查找(bsearch_r 为可重入版本) 7. 哈希/校验函数 SDL_crc16/SDL_crc32:计算 CRC16/CRC32 校验值 SDL_murmur3_32:计算 Murmur3 32 位哈希值 8. 环境变量函数 SDL_getenv/SDL_getenv_unsafe:获取环境变量(_unsafe 版本不做安全检查) SDL_SetEnvironmentVariable/SDL_UnsetEnvironmentVariable:设置/删除环境变量 SDL_GetEnvironmentVariables:获取所有环境变量列表 SDL_CreateEnvironment/SDL_DestroyEnvironment:创建/销毁独立的环境变量上下文 9. 字符编码转换函数 SDL_iconv_open:打开字符编码转换上下文 SDL_iconv:执行编码转换 SDL_iconv_close:关闭转换上下文 SDL_iconv_string:字符串编码转换(简化接口) SDL_UCS4ToUTF8:UCS4 转 UTF-8 编码 SDL_StepUTF8/SDL_StepBackUTF8:UTF-8 字符串步进/回退(遍历字符) 10. 随机数函数 SDL_srand:设置随机数种子 SDL_rand:生成随机整数(替代 rand) SDL_randf:生成 0~1 浮点数随机数 SDL_rand_r/SDL_randf_r:可重入的随机数生成(线程安全) SDL_rand_bits:生成指定位数的随机数 11. 宽字符函数 SDL_wcslen/SDL_wcscmp/SDL_wcsncmp:宽字符串长度/比较 SDL_wcsstr/SDL_wcsnstr:宽字符串查找 SDL_wcslcpy/SDL_wcslcat:宽字符串安全拷贝/拼接 SDL_wcsdup:宽字符串拷贝(自动分配内存) SDL_wcstol:宽字符串转长整数 12. 格式化输入函数 SDL_sscanf/SDL_vsscanf:安全格式化输入(替代 sscanf) SDL_swprintf/SDL_vswprintf:宽字符串格式化输出 数据类型 SDL_malloc_func:内存分配函数指针类型(匹配 SDL_malloc 签名) SDL_calloc_func:内存分配并清零函数指针类型 SDL_realloc_func:内存重分配函数指针类型 SDL_free_func:内存释放函数指针类型 SDL_CompareCallback:排序/查找比较函数类型 SDL_CompareCallback_r:可重入的比较函数类型(带用户数据) SDL_Environment:环境变量上下文类型 SDL_iconv_t:字符编码转换上下文类型 SDL_FunctionPointer:通用函数指针类型 SDL_Time:时间类型(跨平台兼容) Sint8/Sint16/Sint32/Sint64:有符号整数类型(固定位宽) Uint8/Uint16/Uint32/Uint64:无符号整数类型(固定位宽) 结构体 (无) 枚举 (无) 宏 1. 类型转换宏 SDL_static_cast:静态类型转换(替代 C++ static_cast) SDL_reinterpret_cast:重解释类型转换(替代 C++ reinterpret_cast) SDL_const_cast:常量类型转换(替代 C++ const_cast) 2. 数学/工具宏 SDL_min/SDL_max:取最小值/最大值 SDL_clamp:将值限制在指定范围内(clamp(value, min, max)) SDL_arraysize:计算数组元素个数(编译期计算,安全) SDL_FLT_EPSILON:浮点数精度阈值(用于判断浮点数相等) SDL_SIZE_MAX:size_t 类型的最大值 3. 内存初始化宏 SDL_zero:将变量清零(SDL_zero(var)) SDL_zeroa:将数组清零(SDL_zeroa(array)) SDL_zerop:将指针指向的内存清零(SDL_zerop(ptr)) SDL_copyp:指针拷贝(SDL_copyp(dst, src)) SDL_stack_alloc:栈内存分配(临时内存,无需释放) SDL_stack_free:栈内存释放(配套 SDL_stack_alloc) 4. 编译期检查宏 SDL_COMPILE_TIME_ASSERT:编译期断言(失败则编译报错) 5. 格式化输出宏 SDL_PRIs32/SDL_PRIu32:32 位整数格式化占位符(跨平台兼容) SDL_PRIs64/SDL_PRIu64/SDL_PRIx64:64 位整数格式化占位符 SDL_PRINTF_FORMAT_STRING:标记格式化字符串参数(编译器检查) SDL_PRINTF_VARARG_FUNC:标记可变参数格式化函数 6. 编码转换宏 SDL_iconv_utf8_locale:UTF-8 转系统本地编码 SDL_iconv_utf8_ucs2/SDL_iconv_utf8_ucs4:UTF-8 转 UCS2/UCS4 SDL_iconv_wchar_utf8:宽字符转 UTF-8 7. 其他宏 SDL_FOURCC:生成四字符码(用于标识媒体格式等) SDL_SINT64_C/SDL_UINT64_C:64 位常量定义(跨平台兼容) SDL_INVALID_UNICODE_CODEPOINT:无效 Unicode 码点常量 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充核心函数/宏声明(FreeBASIC 绑定可能缺失) #Define SDL_PI_F 3.14159265358979323846f #Define SDL_min(a, b) IIf((a) < (b), (a), (b)) #Define SDL_max(a, b) IIf((a) > (b), (a), (b)) #Define SDL_clamp(x, min_val, max_val) SDL_max(SDL_min((x), (max_val)), (min_val)) ' 函数声明补充 Declare Function SDL_utf8strlen CDecl (ByVal str As ZString Ptr) As Size_t Declare Function SDL_strlcpy CDecl (ByVal dst As ZString Ptr, ByVal src As ZString Ptr, ByVal size As Size_t) As Size_t Declare Function SDL_crc32 CDecl (ByVal crc As Uint32, ByVal data As Const Any Ptr, ByVal len As Size_t) As Uint32 Declare Sub SDL_zero CDecl (ByRef var As Any) Declare Function SDL_randf CDecl () As Float Declare Sub SDL_srand CDecl (ByVal seed As Uint32) ' ==================== 示例 1:安全字符串操作 ==================== Sub StringOperationsExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【安全字符串操作示例】") ' 1. SDL_strlcpy 安全拷贝(防止缓冲区溢出) Dim As ZString * 10 dstBuffer Dim As ZString Ptr src = StrPtr("Hello SDL!") ' 拷贝最多 9 个字符 + 终止符,返回原字符串长度 Dim As Size_t len = SDL_strlcpy(@dstBuffer, src, sizeof(dstBuffer)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "原字符串:%s,长度:%d", src, len) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "拷贝结果:%s(缓冲区大小:%d)", dstBuffer, sizeof(dstBuffer)) ' 2. UTF-8 字符串长度计算 Dim As ZString Ptr utf8Str = StrPtr("SDL 中文示例") Dim As Size_t byteLen = SDL_strlen(utf8Str) ' 字节数 Dim As Size_t charLen = SDL_utf8strlen(utf8Str) ' 字符数 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "UTF-8 字符串:%s", utf8Str) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "字节长度:%d,字符长度:%d", byteLen, charLen) ' 3. 整数转字符串(跨平台兼容) Dim As ZString * 32 numStr SDL_itoa(-12345, @numStr, 10) ' 十进制 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "整数转字符串:%s", numStr) SDL_uitoa(65535, @numStr, 16) ' 十六进制 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "无符号整数转十六进制:%s", numStr) End Sub ' ==================== 示例 2:内存操作与校验 ==================== Sub MemoryOperationsExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【内存操作与校验示例】") ' 1. 内存分配与初始化 Dim As Integer Ptr arr = SDL_calloc(5, sizeof(Integer)) If (arr = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "内存分配失败") Exit Sub End If ' 填充数据 For i As Integer = 0 To 4 arr[i] = i * 10 Next ' 2. 内存拷贝 Dim As Integer Ptr arrCopy = SDL_malloc(5 * sizeof(Integer)) SDL_memcpy(arrCopy, arr, 5 * sizeof(Integer)) ' 打印拷贝结果 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内存拷贝结果:") For i As Integer = 0 To 4 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " arrCopy[%d] = %d", i, arrCopy[i]) Next ' 3. CRC32 校验 Dim As Uint32 crc = SDL_crc32(0, arr, 5 * sizeof(Integer)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "数据 CRC32 校验值:0x%08X", crc) ' 4. 内存释放 SDL_free(arr) SDL_free(arrCopy) ' 5. 内存清零 Type TestStruct a As Integer b As Float c As ZString * 20 End Type Dim As TestStruct ts SDL_zero(ts) ' 清零整个结构体 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "结构体清零后:a=%d, b=%.2f", ts.a, ts.b) End Sub ' ==================== 示例 3:数学与随机数 ==================== Sub MathAndRandomExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【数学与随机数示例】") ' 1. 数学函数 Dim As Float angle = SDL_PI_F / 4 ' 45 度 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "sin(45°) = %.4f", SDL_sinf(angle)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "cos(45°) = %.4f", SDL_cosf(angle)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "sqrt(2) = %.4f", SDL_sqrtf(2.0f)) ' 2. 数值限制(clamp) Dim As Integer val = 150 Dim As Integer clamped = SDL_clamp(val, 0, 100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "clamp(150, 0, 100) = %d", clamped) ' 3. 随机数 SDL_srand(SDL_GetTicks()) ' 以时间为种子 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "随机整数:%d", SDL_rand() Mod 100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "随机浮点数(0~1):%.4f", SDL_randf()) End Sub ' ==================== 示例 4:环境变量操作 ==================== Sub EnvVarExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【环境变量操作示例】") ' 1. 设置环境变量 SDL_SetEnvironmentVariable(StrPtr("SDL_TEST_VAR"), StrPtr("Hello SDL Env")) ' 2. 获取环境变量 Dim As ZString Ptr envVal = SDL_getenv(StrPtr("SDL_TEST_VAR")) If (envVal <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "获取环境变量 SDL_TEST_VAR:%s", envVal) End If ' 3. 删除环境变量 SDL_UnsetEnvironmentVariable(StrPtr("SDL_TEST_VAR")) envVal = SDL_getenv(StrPtr("SDL_TEST_VAR")) If (envVal = NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "环境变量 SDL_TEST_VAR 已删除") End If End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(Stdinc 子系统无需特定初始化) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 StringOperationsExample() MemoryOperationsExample() MathAndRandomExample() EnvVarExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 核心设计理念: SDL_stdinc 的核心目标是「跨平台一致性」,而非「替代标准库」; 对于底层实现稳定的函数(如 memcpy),SDL 会直接调用平台原生版本,保证性能; 对于行为不一致/缺失的函数(如 itoa/snprintf),SDL 提供自研实现,保证跨平台表现相同。 内存管理最佳实践: SDL 内存函数(SDL_malloc/SDL_free 等)必须配对使用,不可混用标准库 free; SDL_calloc 会自动清零内存,优先用于需要初始化的场景; SDL_GetNumAllocations 可用于调试内存泄漏(记录分配/释放的数量差); 自定义内存函数需在 SDL 初始化前通过 SDL_SetMemoryFunctions 设置。 字符串安全要点: 优先使用 SDL_strlcpy/SDL_strlcat 替代 strcpy/strcat,避免缓冲区溢出; SDL_utf8strlen 是 UTF-8 字符串的「字符数」统计,SDL_strlen 是「字节数」统计; SDL_asprintf 会自动分配内存,使用后必须调用 SDL_free 释放。 跨平台兼容注意: 64 位整数格式化需使用 SDL_PRId64/SDL_PRIu64 等宏,避免 %lld/%llu 的平台差异; 整数类型优先使用 Sint32/Uint32 等固定位宽类型,而非 int/long; 随机数函数 SDL_rand 比标准 rand 更稳定,且 SDL_rand_r 保证线程安全。 总结 核心优势: 解耦 C 运行时依赖,降低跨平台编译复杂度; 统一函数行为,避免不同平台的标准库实现差异; 补充安全/增强功能(如 SDL_strlcpy/SDL_crc32),提升代码健壮性; 底层优化实现,兼顾性能与兼容性。 使用建议: 新项目优先使用 SDL_stdinc 函数替代标准库函数,减少跨平台问题; 内存分配/释放必须使用 SDL 配套函数(SDL_malloc ↔ SDL_free); UTF-8 字符串操作使用 SDL_utf8* 系列函数,避免多字节字符处理错误; 编译期使用 SDL_COMPILE_TIME_ASSERT 检查类型大小、常量等,提前发现问题。 关键点回顾: SDL_stdinc 是 SDL 的基础工具集,提供跨平台一致的 C 运行时函数; SDL_strlcpy/SDL_snprintf 等函数解决了标准库字符串操作的安全问题; 内存函数、数学函数、随机数函数均做了跨平台兼容和性能优化; 固定位宽类型(Sint32/Uint64)和格式化宏(SDL_PRIs64)是跨平台开发的关键。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_系统适配(CategorySystem) 2026-3-7
      SDL3_API分类参考_系统适配(CategorySystem) 系统适配子系统(CategorySystem) SDL 提供的平台专属 API 集合,这类函数用于处理特定操作系统的个性化需求——由于其功能高度依赖平台特性,无法抽象为跨平台通用接口。 大多数应用无需使用这些函数即可正常运行,但在以下场景中能发挥关键作用: 与特定系统的其他组件集成(如 Android 的 JNI、Windows 的消息钩子); 为应用添加平台专属的体验优化(如 iOS 动画回调、Android 吐司提示); 解决仅影响单一目标平台的问题(如 Linux 线程优先级、X11 事件钩子)。 函数 Android 平台专属 SDL_GetAndroidActivity:获取 Android 应用的 Activity 实例指针(JNI 交互核心) SDL_GetAndroidCachePath:获取 Android 应用的缓存目录路径(应用卸载后会被清除) SDL_GetAndroidExternalStoragePath:获取 Android 外部存储(SD 卡)根路径 SDL_GetAndroidExternalStorageState:获取外部存储状态(如是否挂载、可读写) SDL_GetAndroidInternalStoragePath:获取 Android 内部存储(应用私有目录)路径 SDL_GetAndroidJNIEnv:获取 Android 应用的 JNIEnv 环境指针(用于调用 Java 方法) SDL_GetAndroidSDKVersion:获取设备的 Android SDK 版本号(如 30 对应 Android 11) SDL_RequestAndroidPermission:向 Android 系统申请权限(如存储、相机),异步返回结果 SDL_SendAndroidBackButton:模拟 Android 物理返回键事件(触发应用返回逻辑) SDL_SendAndroidMessage:向 Android 原生层发送自定义消息(JNI 通信) SDL_ShowAndroidToast:显示 Android 原生吐司提示(短/长时间悬浮提示) Windows 平台专属 SDL_GetDirect3D9AdapterIndex:获取 Direct3D 9 显卡适配器索引(适配多显卡) SDL_GetDXGIOutputInfo:获取 DXGI 输出设备信息(用于多显示器适配) SDLSetWindowsMessageHook:设置 Windows 消息钩子(拦截/处理系统消息如 WM*) Linux 平台专属 SDL_SetLinuxThreadPriority:设置 Linux 线程优先级(调整调度优先级) SDL_SetLinuxThreadPriorityAndPolicy:设置 Linux 线程优先级及调度策略(如 SCHED_FIFO) SDL_SetX11EventHook:设置 X11 事件钩子(拦截/处理 X11 窗口系统事件) iOS 平台专属 SDL_SetiOSAnimationCallback:设置 iOS 动画回调(同步应用动画与系统刷新率) SDL_SetiOSEventPump:设置 iOS 事件泵(自定义事件处理逻辑) SDL_OnApplicationDidChangeStatusBarOrientation:iOS 状态栏方向变更回调 SDL_OnApplicationDidEnterBackground:iOS 应用进入后台回调 SDL_OnApplicationDidEnterForeground:iOS 应用进入前台回调 SDL_OnApplicationDidReceiveMemoryWarning:iOS 内存警告回调 SDL_OnApplicationWillEnterBackground:iOS 应用即将进入后台回调 SDL_OnApplicationWillEnterForeground:iOS 应用即将进入前台回调 SDL_OnApplicationWillTerminate:iOS 应用即将终止回调 游戏主机/特殊平台 SDL_GetGDKDefaultUser:获取 GDK(Xbox 开发工具包)默认用户实例 SDL_GetGDKTaskQueue:获取 GDK 任务队列(异步任务调度) 跨平台检测类 SDL_GetSandbox:获取应用的沙箱模式状态(判断是否运行在受限环境) SDL_IsChromebook:检测设备是否为 Chromebook(ChromeOS 设备) SDL_IsDeXMode:检测三星设备是否处于 DeX 模式(桌面化模式) SDL_IsTablet:检测设备是否为平板(区分手机/平板) SDL_IsTV:检测设备是否为智能电视(如 Android TV、Tizen TV) 数据类型 SDL_iOSAnimationCallback:iOS 动画回调函数类型(同步应用动画帧) SDL_RequestAndroidPermissionCallback:Android 权限申请结果回调类型(返回权限是否授予) SDL_WindowsMessageHook:Windows 消息钩子函数类型(处理系统消息) SDL_X11EventHook:X11 事件钩子函数类型(处理 X11 窗口事件) 结构体 (无) 枚举 SDL_Sandbox:沙箱模式枚举,标识应用运行的沙箱环境类型: SDL_SANDBOX_UNKNOWN:未知沙箱状态 SDL_SANDBOX_NONE:无沙箱限制(普通桌面应用) SDL_SANDBOX_APPLE:Apple 沙箱(macOS/iOS 应用) SDL_SANDBOX_ANDROID:Android 沙箱(应用私有目录限制) SDL_SANDBOX_LINUX:Linux 沙箱(如 Flatpak/Snap 容器) 宏 SDL_ANDROID_EXTERNAL_STORAGE_READ:Android 外部存储读权限标志 SDL_ANDROID_EXTERNAL_STORAGE_WRITE:Android 外部存储写权限标志 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充平台专属类型/函数声明(FreeBASIC 绑定可能缺失) ' ==================== Android 平台声明 ==================== #If Defined(SDL_PLATFORM_ANDROID) ' Android 权限申请回调类型 Type SDL_RequestAndroidPermissionCallback As Sub( _ ByVal permission As ZString Ptr, _ ByVal granted As SDL_bool, _ ByVal userdata As Any Ptr _ ) ' Android 函数声明 Declare Function SDL_GetAndroidCachePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidExternalStoragePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidInternalStoragePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidSDKVersion CDecl () As Integer Declare Sub SDL_ShowAndroidToast CDecl (ByVal text As ZString Ptr, ByVal duration As Integer) Declare Function SDL_RequestAndroidPermission CDecl ( _ ByVal permission As ZString Ptr, _ ByVal callback As SDL_RequestAndroidPermissionCallback, _ ByVal userdata As Any Ptr _ ) As SDL_bool ' Android Toast 时长常量 Const SDL_ANDROID_TOAST_SHORT = 0 Const SDL_ANDROID_TOAST_LONG = 1 ' Android 权限常量 Const SDL_ANDROID_PERMISSION_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE" #EndIf ' ==================== Windows 平台声明 ==================== #If Defined(SDL_PLATFORM_WINDOWS) ' Windows 消息钩子类型 Type SDL_WindowsMessageHook As Function( _ ByVal hwnd As HWND, _ ByVal msg As Uint32, _ ByVal wparam As WPARAM, _ ByVal lparam As LPARAM, _ ByVal userdata As Any Ptr, _ ByRef retval As LRESULT _ ) As SDL_bool ' Windows 函数声明 Declare Sub SDL_SetWindowsMessageHook CDecl ( _ ByVal hook As SDL_WindowsMessageHook, _ ByVal userdata As Any Ptr _ ) #EndIf ' ==================== Linux 平台声明 ==================== #If Defined(SDL_PLATFORM_LINUX) ' Linux 线程优先级函数声明 Declare Function SDL_SetLinuxThreadPriority CDecl ( _ ByVal thread As SDL_ThreadID, _ ByVal priority As Integer _ ) As SDL_bool #EndIf ' ==================== 跨平台检测函数 ==================== Declare Function SDL_GetSandbox CDecl () As Integer Declare Function SDL_IsTablet CDecl () As SDL_bool Declare Function SDL_IsTV CDecl () As SDL_bool ' ==================== 示例函数 ==================== ' Android 示例:获取存储路径并显示 Toast Sub AndroidStorageExample() #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【Android 存储路径示例】") ' 获取各类存储路径 Dim As ZString Ptr cachePath = SDL_GetAndroidCachePath() Dim As ZString Ptr externalPath = SDL_GetAndroidExternalStoragePath() Dim As ZString Ptr internalPath = SDL_GetAndroidInternalStoragePath() If (cachePath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "缓存目录:%s", cachePath) End If If (externalPath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "外部存储目录:%s", externalPath) End If If (internalPath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内部存储目录:%s", internalPath) End If ' 获取 SDK 版本 Dim As Integer sdkVersion = SDL_GetAndroidSDKVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Android SDK 版本:%d", sdkVersion) ' 显示 Toast 提示 SDL_ShowAndroidToast(StrPtr("存储路径获取成功!"), SDL_ANDROID_TOAST_SHORT) #Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "非 Android 平台,跳过存储路径示例") #EndIf End Sub ' Android 示例:申请存储权限 Sub AndroidPermissionExample() #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【Android 权限申请示例】") ' 权限申请回调函数 Sub PermissionCallback( _ ByVal permission As ZString Ptr, _ ByVal granted As SDL_bool, _ ByVal userdata As Any Ptr _ ) If (granted = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "权限 %s 申请成功", permission) SDL_ShowAndroidToast(StrPtr("存储权限已授予!"), SDL_ANDROID_TOAST_SHORT) Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "权限 %s 申请失败", permission) SDL_ShowAndroidToast(StrPtr("存储权限申请失败!"), SDL_ANDROID_TOAST_SHORT) End If End Sub ' 申请外部存储写权限 Dim As SDL_bool result = SDL_RequestAndroidPermission( _ StrPtr(SDL_ANDROID_PERMISSION_WRITE_EXTERNAL_STORAGE), _ @PermissionCallback, _ NULL _ ) If (result = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "申请权限失败:%s", SDL_GetError()) End If #Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "非 Android 平台,跳过权限申请示例") #EndIf End Sub ' 跨平台示例:设备类型检测 Sub DeviceDetectionExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【跨平台设备检测示例】") ' 检测沙箱模式 Dim As Integer sandbox = SDL_GetSandbox() Select Case sandbox Case 0: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:未知") Case 1: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:无限制") Case 2: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Apple 沙箱") Case 3: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Android 沙箱") Case 4: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Linux 沙箱") End Select ' 检测设备类型 If (SDL_IsTablet() = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:平板") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:非平板(手机/桌面)") End If If (SDL_IsTV() = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:智能电视") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:非智能电视") End If End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 DeviceDetectionExample() AndroidStorageExample() AndroidPermissionExample() ' 保持应用运行(Android 需等待权限回调) #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "等待权限申请结果...") Dim As Integer waitCount = 0 While (waitCount < 10) SDL_Delay(1000) waitCount += 1 Wend #EndIf ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 平台专属函数使用原则: 必须通过 #If Defined(SDL_PLATFORM_XXX) 做条件编译,避免跨平台编译错误; 非目标平台调用这些函数会返回默认值(如 NULL/SDL_FALSE),需做好容错; 优先使用跨平台 API,仅在必要时使用平台专属函数(降低维护成本)。 Android 平台关键注意事项: Android 10+ 需申请 MANAGE_EXTERNAL_STORAGE 权限才能访问公共目录,传统存储权限已失效; SDL_ShowAndroidToast 需在主线程调用,子线程调用可能无响应; 存储路径返回的字符串由 SDL 管理,无需手动释放,但不可修改。 Windows/Linux 平台关键注意事项: Windows 消息钩子需在主线程设置,且需在退出前移除(避免崩溃); Linux 线程优先级设置需要 root 权限,普通用户调用可能失败; X11 事件钩子仅在 X11 窗口系统下生效,Wayland 环境需适配其他接口。 沙箱模式影响: 沙箱类型 核心限制 适配建议 Apple 沙箱 无法访问外部文件、网络需配置权限 使用应用沙箱内目录存储数据 Android 沙箱 仅可访问应用私有目录、公共目录需权限 优先使用内部存储,避免依赖外部存储 Linux 沙箱 权限受限、文件系统隔离 适配 Flatpak/Snap 的目录结构 总结 核心优势: 提供一站式平台专属能力,无需直接调用原生 API(如 Android JNI、Windows Win32); 封装了平台特有的复杂逻辑(如权限申请、消息钩子),降低开发难度; 保持接口风格统一,跨平台代码只需少量条件编译即可适配。 使用建议: 平台专属函数仅在「跨平台 API 无法满足需求」时使用; 调用前必须做平台检测,避免非目标平台编译/运行错误; Android/iOS 等移动平台函数需注意主线程/子线程调用限制; 权限相关函数需处理用户拒绝的情况,保证应用容错性。 关键点回顾: CategorySystem 是 SDL 的平台专属函数集合,无跨平台通用逻辑; 调用平台专属函数前需通过 SDL_PLATFORM_XXX 宏做条件编译; Android 权限申请、Windows 消息钩子、Linux 线程优先级是该模块的高频使用场景; 沙箱模式检测可帮助应用适配不同平台的权限限制,避免运行时错误。
      • 2026年-3月-7日
      • 3 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_区域设置(CategoryLocale) 2026-3-7
      SDL3_API分类参考_区域设置(CategoryLocale) 区域设置子系统(CategoryLocale) SDL 提供了轻量的区域设置服务,核心能力是获取用户的首选区域列表(由「语言 + 国家/地区」组成)。该子系统仅包含一个核心函数:SDL_GetPreferredLocales(),它会自动处理不同系统、不同配置方式下的语言设置解析,兼容各类复杂的用户语言配置场景(如多语言优先级、地区变体等)。 这一功能是实现应用多语言适配的基础——通过获取用户的首选语言,应用可自动切换界面文本、音频、字体等资源,提升本地化体验。 函数 SDL_GetPreferredLocales:获取用户的首选区域设置列表,返回 SDL_Locale 结构体数组(数组末尾以 NULL 结尾);函数内部自动分配内存,调用者需通过 SDL_free() 释放整个数组 数据类型 (无) 结构体 SDL_Locale:区域设置结构体,包含两个核心字段: language:语言代码(符合 ISO 639 标准,如 "zh" 表示中文、"en" 表示英文、"ja" 表示日文) country:国家/地区代码(符合 ISO 3166 标准,如 "CN" 表示中国、"US" 表示美国、"TW" 表示中国台湾);若未指定地区,该字段为 NULL 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充结构体和函数声明(FreeBASIC 绑定可能缺失) Type SDL_Locale language As ZString Ptr ' 语言代码(如 "zh"、"en") country As ZString Ptr ' 国家/地区代码(如 "CN"、"US",NULL 表示未指定) End Type Declare Function SDL_GetPreferredLocales CDecl () As SDL_Locale Ptr Declare Sub SDL_free CDecl (ByVal ptr As Any Ptr) ' 打印区域设置信息 Sub PrintLocaleInfo(ByVal locale As SDL_Locale Ptr) If (locale = NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - 无区域信息") Exit Sub End If ' 拼接语言+地区字符串(如 "zh-CN"、"en-US") Dim As ZString * 32 localeStr If (locale->country <> NULL) Then snprintf(@localeStr, sizeof(localeStr), "%s-%s", *locale->language, *locale->country) Else snprintf(@localeStr, sizeof(localeStr), "%s", *locale->language) End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - %s", localeStr) ' 补充语言/地区说明 If (strcmp(locale->language, "zh") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:中文") If (locale->country <> NULL) Then If (strcmp(locale->country, "CN") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国大陆") ElseIf (strcmp(locale->country, "TW") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国台湾") ElseIf (strcmp(locale->country, "HK") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国香港") End If End If ElseIf (strcmp(locale->language, "en") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:英文") If (locale->country <> NULL And strcmp(locale->country, "US") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:美国") ElseIf (locale->country <> NULL And strcmp(locale->country, "GB") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:英国") End If ElseIf (strcmp(locale->language, "ja") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:日文") End If End Sub ' 获取并解析用户首选区域列表 Sub GetPreferredLocalesExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【获取用户首选区域设置】") ' 1. 获取首选区域列表(SDL 自动分配内存) Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales() If (locales = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "获取区域设置失败:%s", SDL_GetError()) Exit Sub End If ' 2. 遍历并打印所有区域设置(数组以 NULL 结尾) Dim As Integer i = 0 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户首选区域列表(按优先级排序):") While (locales[i].language <> NULL) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "第 %d 项:", i + 1) PrintLocaleInfo(@locales[i]) i += 1 Wend If (i = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未获取到任何区域设置") End If ' 3. 释放 SDL 分配的内存(必须调用,避免内存泄漏) SDL_free(locales) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "区域设置内存已释放") End Sub ' 根据区域设置选择应用语言 Sub SelectAppLanguage() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据区域设置选择应用语言】") Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales() If (locales = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "使用默认语言:英文") Exit Sub End If ' 遍历首选区域列表,匹配支持的语言 Dim As ZString Ptr appLang = StrPtr("en") ' 默认语言:英文 Dim As Integer i = 0 While (locales[i].language <> NULL) ' 检查是否支持该语言 If (strcmp(locales[i].language, "zh") = 0) Then appLang = StrPtr("zh") ' 进一步区分简繁(根据地区) If (locales[i].country <> NULL) Then If (strcmp(locales[i].country, "TW") = 0 Or strcmp(locales[i].country, "HK") = 0) Then appLang = StrPtr("zh-TW") ' 繁体中文 Else appLang = StrPtr("zh-CN") ' 简体中文 End If End If Exit While ' 匹配到首选语言,停止遍历 ElseIf (strcmp(locales[i].language, "ja") = 0) Then appLang = StrPtr("ja") ' 日文 Exit While End If i += 1 Wend ' 输出选择结果 Select Case *appLang Case "zh-CN": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:简体中文") Case "zh-TW": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:繁体中文") Case "ja": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:日文") Case Else: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:英文(默认)") End Select ' 释放内存 SDL_free(locales) End Sub ' 主程序 Sub Main() ' 初始化 SDL(Locale 子系统无需特定子系统,基础初始化即可) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 GetPreferredLocalesExample() SelectAppLanguage() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 区域代码规范: 语言代码遵循 ISO 639-1(两位小写,如 zh=中文、en=英文、fr=法语); 地区代码遵循 ISO 3166-1 alpha-2(两位大写,如 CN=中国、US=美国、JP=日本); 组合格式为 语言-地区(如 zh-CN=简体中文(中国大陆)、en-US=美式英语、zh-TW=繁体中文(中国台湾))。 平台实现逻辑: 平台 获取语言设置的原生方式 SDL 封装优势 Windows GetUserPreferredUILanguages 自动处理多语言优先级、兼容旧系统版本 macOS CFLocaleCopyPreferredLanguages 统一返回格式,无需处理 CoreFoundation 类型 Linux 读取 LANG/LC_* 环境变量 解析复杂的 locale 字符串(如 zh_CN.UTF-8) 移动平台 Android: getResources().getConfiguration()iOS: NSLocale 跨平台统一返回 SDL_Locale 结构体 内存管理注意: SDL_GetPreferredLocales() 返回的数组由 SDL 分配内存,必须调用 SDL_free() 释放,否则会导致内存泄漏; 数组内的 language/country 字符串是数组内存的一部分,无需单独释放; 数组以 language = NULL 的元素结尾,遍历需以此为终止条件。 常见区域设置示例: 区域字符串 含义 应用适配建议 zh-CN 简体中文(中国大陆) 使用简体中文字体、简体文本资源 zh-TW 繁体中文(中国台湾) 使用繁体中文字体、繁体文本资源 en-US 美式英语 使用美式拼写(如 color/center) en-GB 英式英语 使用英式拼写(如 colour/centre) ja-JP 日文(日本) 使用日文字体、日文文本资源 总结 核心优势: 跨平台统一的区域设置获取接口,无需适配不同系统的原生语言 API; 自动解析复杂的系统语言配置,返回标准化的「语言+地区」格式; 轻量易用,仅一个核心函数即可完成所有逻辑,降低本地化开发成本。 使用建议: 应用启动时调用 SDL_GetPreferredLocales(),优先匹配用户首选语言; 按优先级遍历区域列表,匹配到支持的语言后立即停止(无需遍历全部); 必须调用 SDL_free() 释放返回的数组,避免内存泄漏; 对未匹配到的语言,默认使用英文(或应用核心语言)保证可用性。 关键点回顾: SDL_GetPreferredLocales() 是区域设置子系统的唯一核心函数,返回按优先级排序的 SDL_Locale 数组; SDL_Locale 包含 language(语言代码)和 country(地区代码)两个字段,地区代码可能为 NULL; 返回的数组必须通过 SDL_free() 释放,这是避免内存泄漏的关键; 区域设置是应用本地化的基础,需结合文本资源、字体、格式适配等功能使用。
      • 2026年-3月-7日
      • 3 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_系统托盘(CategoryTray) 2026-3-7
      SDL3_API分类参考_系统托盘(CategoryTray) 系统托盘子系统(CategoryTray) SDL 提供了系统托盘(Windows 中更准确的称呼是「通知区域」)操作接口,在支持该功能的平台上(Windows/macOS/Linux 主流桌面环境),SDL 应用可创建托盘图标、添加子菜单、复选框、可点击菜单项,并注册回调函数响应用户的点击操作。 系统托盘功能让应用在后台运行时仍能与用户交互,是桌面应用的常用特性(如后台服务、工具类软件)。 函数 SDL_CreateTray:创建基础系统托盘实例,返回 SDL_Tray 句柄(失败返回 NULL,需初始化视频子系统) SDL_CreateTrayWithProperties:创建带自定义属性的托盘实例(支持图标、提示文本等初始配置) SDL_DestroyTray:销毁托盘实例,移除系统托盘中的图标和菜单,释放所有关联资源 SDL_SetTrayIcon:设置托盘图标(传入 SDL_Surface 或 SDL_Texture 类型的图标资源) SDL_SetTrayTooltip:设置托盘图标的悬浮提示文本(鼠标悬停时显示) SDL_CreateTrayMenu:创建托盘菜单容器,用于存放菜单项 SDL_CreateTraySubmenu:创建子菜单(嵌套在主菜单中的二级菜单) SDL_InsertTrayEntryAt:在指定位置插入托盘菜单项(支持普通项、复选框、分隔符等) SDL_RemoveTrayEntry:移除指定的托盘菜单项 SDL_SetTrayEntryLabel:设置菜单项的显示文本 SDL_SetTrayEntryChecked:设置复选框类型菜单项的选中状态 SDL_GetTrayEntryChecked:获取复选框菜单项的选中状态 SDL_SetTrayEntryEnabled:设置菜单项是否可用(禁用时灰显,无法点击) SDL_GetTrayEntryEnabled:获取菜单项的启用状态 SDL_GetTrayEntryLabel:获取菜单项的显示文本 SDL_SetTrayEntryCallback:为菜单项注册点击回调函数 SDL_ClickTrayEntry:手动触发菜单项的点击事件(模拟用户操作) SDL_GetTrayEntries:获取指定菜单下的所有菜单项列表 SDL_GetTrayEntryParent:获取菜单项所属的父菜单/父托盘 SDL_GetTrayMenu:获取托盘实例关联的主菜单 SDL_GetTraySubmenu:获取菜单项关联的子菜单(若有) SDL_GetTrayMenuParentEntry:获取子菜单所属的父菜单项 SDL_GetTrayMenuParentTray:获取菜单所属的父托盘实例 SDL_UpdateTrays:更新所有托盘实例的显示(修改菜单/图标后需调用) 数据类型 SDL_Tray:系统托盘实例句柄类型,封装平台相关的托盘资源(如 Windows 的 NOTIFYICONDATA) SDL_TrayMenu:托盘菜单容器类型,管理多个菜单项的集合 SDL_TrayEntry:托盘菜单项类型,代表单个可点击/可选的菜单元素(普通项、复选框、子菜单、分隔符) SDL_TrayEntryFlags:菜单项标志类型,标识菜单项类型(普通项、复选框、分隔符、子菜单等) SDL_TrayCallback:菜单项通用回调函数类型,响应菜单项的状态变更 SDL_TrayClickCallback:菜单项点击回调函数类型,用户点击菜单项时触发 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充类型/函数声明(FreeBASIC 绑定可能缺失) Type SDL_Tray As Any Ptr Type SDL_TrayMenu As Any Ptr Type SDL_TrayEntry As Any Ptr Type SDL_TrayEntryFlags As Uint32 ' 菜单项类型标志(示例值,实际 SDL 定义以官方为准) Const SDL_TRAYENTRY_NORMAL = 0 ' 普通菜单项 Const SDL_TRAYENTRY_CHECKBOX = 1 Shl 0 ' 复选框菜单项 Const SDL_TRAYENTRY_SEPARATOR = 1 Shl 1 ' 分隔符 Const SDL_TRAYENTRY_SUBMENU = 1 Shl 2 ' 子菜单入口 ' 回调函数类型定义 Type SDL_TrayClickCallback As Sub( _ ByVal entry As SDL_TrayEntry, _ ByVal userdata As Any Ptr _ ) ' 核心函数声明 Declare Function SDL_CreateTray CDecl () As SDL_Tray Declare Sub SDL_DestroyTray CDecl (ByVal tray As SDL_Tray) Declare Function SDL_SetTrayIcon CDecl (ByVal tray As SDL_Tray, ByVal icon As SDL_Surface Ptr) As SDL_bool Declare Function SDL_SetTrayTooltip CDecl (ByVal tray As SDL_Tray, ByVal tooltip As ZString Ptr) As SDL_bool Declare Function SDL_CreateTrayMenu CDecl () As SDL_TrayMenu Declare Function SDL_InsertTrayEntryAt CDecl ( _ ByVal menu As SDL_TrayMenu, _ ByVal index As Integer, _ ByVal flags As SDL_TrayEntryFlags, _ ByVal label As ZString Ptr, _ ByVal userdata As Any Ptr _ ) As SDL_TrayEntry Declare Function SDL_CreateTraySubmenu CDecl (ByVal entry As SDL_TrayEntry) As SDL_TrayMenu Declare Sub SDL_SetTrayEntryCallback CDecl (ByVal entry As SDL_TrayEntry, ByVal callback As SDL_TrayClickCallback) Declare Sub SDL_SetTrayEntryChecked CDecl (ByVal entry As SDL_TrayEntry, ByVal checked As SDL_bool) Declare Function SDL_GetTrayEntryChecked CDecl (ByVal entry As SDL_TrayEntry) As SDL_bool Declare Sub SDL_SetTrayEntryEnabled CDecl (ByVal entry As SDL_TrayEntry, ByVal enabled As SDL_bool) Declare Function SDL_GetTrayMenu CDecl (ByVal tray As SDL_Tray) As SDL_TrayMenu Declare Sub SDL_SetTrayMenu CDecl (ByVal tray As SDL_Tray, ByVal menu As SDL_TrayMenu) Declare Sub SDL_UpdateTrays CDecl () ' 全局托盘实例 Dim Shared As SDL_Tray g_tray = NULL ' 全局退出标志 Dim Shared As SDL_bool g_quit = SDL_FALSE ' 菜单项点击回调:显示主窗口 Sub ShowWindowCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「显示窗口」") ' 模拟显示主窗口逻辑 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 显示应用主窗口") End Sub ' 菜单项点击回调:切换静音状态 Sub ToggleMuteCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「静音模式」") ' 切换复选框状态 Dim As SDL_bool checked = SDL_GetTrayEntryChecked(entry) SDL_SetTrayEntryChecked(entry, Not checked) ' 刷新托盘显示 SDL_UpdateTrays() ' 模拟静音逻辑 If (Not checked) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 开启静音模式") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 关闭静音模式") End If End Sub ' 菜单项点击回调:退出应用 Sub ExitAppCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「退出」") g_quit = SDL_TRUE End Sub ' 创建系统托盘及菜单 Function CreateSystemTray() As SDL_bool ' 1. 创建托盘实例 g_tray = SDL_CreateTray() If (g_tray = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建托盘失败:%s", SDL_GetError()) Return SDL_FALSE End If ' 2. 设置托盘提示文本(鼠标悬浮显示) If (SDL_SetTrayTooltip(g_tray, StrPtr("SDL 托盘示例")) = SDL_FALSE) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "设置托盘提示失败:%s", SDL_GetError()) End If ' 3. 创建托盘主菜单 Dim As SDL_TrayMenu Ptr mainMenu = SDL_CreateTrayMenu() If (mainMenu = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建主菜单失败:%s", SDL_GetError()) SDL_DestroyTray(g_tray) Return SDL_FALSE End If ' 4. 添加菜单项:显示窗口(普通项) Dim As SDL_TrayEntry Ptr showWindowEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 0, _ SDL_TRAYENTRY_NORMAL, _ StrPtr("显示窗口"), _ NULL _ ) If (showWindowEntry <> NULL) Then SDL_SetTrayEntryCallback(showWindowEntry, @ShowWindowCallback) End If ' 5. 添加菜单项:分隔符 SDL_InsertTrayEntryAt( _ mainMenu, _ 1, _ SDL_TRAYENTRY_SEPARATOR, _ NULL, _ NULL _ ) ' 6. 添加菜单项:静音模式(复选框) Dim As SDL_TrayEntry Ptr muteEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 2, _ SDL_TRAYENTRY_CHECKBOX, _ StrPtr("静音模式"), _ NULL _ ) If (muteEntry <> NULL) Then SDL_SetTrayEntryChecked(muteEntry, SDL_FALSE) ' 默认未选中 SDL_SetTrayEntryCallback(muteEntry, @ToggleMuteCallback) End If ' 7. 添加菜单项:退出(普通项) Dim As SDL_TrayEntry Ptr exitEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 3, _ SDL_TRAYENTRY_NORMAL, _ StrPtr("退出"), _ NULL _ ) If (exitEntry <> NULL) Then SDL_SetTrayEntryCallback(exitEntry, @ExitAppCallback) End If ' 8. 将菜单关联到托盘 SDL_SetTrayMenu(g_tray, mainMenu) ' 9. 更新托盘显示 SDL_UpdateTrays() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统托盘创建成功") Return SDL_TRUE End Function ' 主程序 Sub Main() ' 初始化 SDL(必须初始化视频子系统) If (SDL_Init(SDL_INIT_VIDEO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 创建系统托盘 If (CreateSystemTray() = SDL_FALSE) Then SDL_Quit() Exit Sub End If ' 主事件循环(保持应用运行,等待用户操作) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用后台运行中,点击托盘「退出」结束程序...") While (g_quit = SDL_FALSE) Dim As SDL_Event evt ' 处理 SDL 事件(托盘点击事件需通过事件循环分发) While (SDL_PollEvent(@evt)) If (evt.type = SDL_QUIT) Then g_quit = SDL_TRUE End If Wend SDL_Delay(100) ' 降低CPU占用 Wend ' 销毁托盘实例 If (g_tray <> NULL) Then SDL_DestroyTray(g_tray) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统托盘已销毁") End If ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 关键前置条件: 必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),托盘依赖窗口系统资源; 托盘创建后需调用 SDL_UpdateTrays() 才能生效(修改菜单/图标后也需调用); 应用需保持事件循环运行,否则无法响应托盘点击事件。 菜单项类型说明: 标志常量 菜单项类型 用途 SDL_TRAYENTRY_NORMAL 普通菜单项 点击触发回调(如「显示窗口」「退出」) SDL_TRAYENTRY_CHECKBOX 复选框项 可选中/取消选中(如「静音模式」) SDL_TRAYENTRY_SEPARATOR 分隔符 视觉分隔不同功能的菜单项 SDL_TRAYENTRY_SUBMENU 子菜单入口 点击展开二级菜单 平台兼容性: 平台 支持情况 特殊说明 Windows 完全支持(所有功能) 托盘图标显示在通知区域,支持所有菜单项类型 macOS 完全支持(所有功能) 托盘图标显示在菜单栏右侧,样式适配macOS Linux 大部分支持(依赖桌面环境) GNOME/KDE 支持良好,轻量桌面可能部分功能失效 移动平台 不支持 无系统托盘概念 资源管理注意: 必须调用 SDL_DestroyTray() 销毁托盘实例,否则会导致资源泄漏(尤其 Windows 平台); 菜单项的用户数据(userdata)需自行管理生命周期,避免悬空指针; 托盘图标建议使用 16x16/32x32 尺寸的 PNG/BMP,保证不同 DPI 下显示清晰。 总结 核心优势: 跨平台统一的系统托盘接口,无需适配 Windows 的 Shell_NotifyIcon、macOS 的 NSStatusItem 等原生 API; 支持丰富的菜单类型(普通项、复选框、子菜单、分隔符),满足桌面应用的交互需求; 回调机制清晰,可精准响应用户对菜单项的点击操作; 与 SDL 事件循环无缝集成,保证应用后台运行时的响应性。 使用建议: 托盘创建后需关联菜单才能显示右键菜单,空托盘仅显示图标无交互; 复选框菜单项需手动调用 SDL_SetTrayEntryChecked() 切换状态,并调用 SDL_UpdateTrays() 刷新; 退出应用前必须销毁托盘实例,避免残留托盘图标(Windows 平台易出现此问题); 托盘图标建议提供多分辨率版本,适配不同系统的显示缩放比例。 关键点回顾: SDL_Tray 是托盘核心句柄,所有托盘操作均基于此; 修改托盘菜单/图标后必须调用 SDL_UpdateTrays() 才能生效; 菜单项点击回调需配合 SDL 事件循环才能触发,应用需保持事件循环运行; 不同平台的托盘样式有差异,但接口行为一致,无需额外适配。
      • 2026年-3月-7日
      • 3 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • 1
    • 2
    • 3
    博主栏壁纸
    博主头像 勇芳

    330 文章数
    0 评论量
    • QQ游戏大厅多开版_旧版_2012到2025版
    • 使用Sandboxie沙盒多开QQ游戏大厅
    • Sandboxie沙盒(隔离软件)
    人生倒计时
    最新评论
    链接
    • 公益·寻亲,让爱回家
    • Visual Basic6 语言和控件手册
    • CWindow类库帮助FreeBasic版
    • FreeBASIC 帮助文档中文版
    • Windows GDI 编程手册
    • Windows GDI+ 编程手册
    • SQLite3数据库API手册
    • WebBrowser控件编程手册
    • Win32API参考手册
    • Windows 编程宝典
    • WinHttp参考资料
    • WMI编程手册
    • VisualFreeBasic编程文档
    舔狗日记
    载入天数...载入时分秒...

    © 2025 勇芳软件工作室 版权所有

    ICP备案图标 浙ICP备11006222号-1 | 公安备案图标 33100402331731号

    powered by emlog 浙ICP备11006222号-1