VisualFreeBasic的编程文档和教程
论坛的首页 勇芳的软件
教程和帮助
  • VisualFreeBasic编程文档
  • 勇芳系列软件帮助说明教程
  • 留言或交流 登录
    登录
    侧边栏壁纸
    博主头像
    勇芳

    • 累计撰写 330 篇文章
    • 累计收到 0 条评论
    • 首页
    • 栏目
      • 论坛的首页
      • 勇芳的软件
      • 教程和帮助
        • VisualFreeBasic编程文档
        • 勇芳系列软件帮助说明教程
      • 留言或交流
      • 登录
    VisualFreeBasic编程文档
    • SDL3_API分类参考_文件对话框(CategoryDialog) 2026-3-7
      SDL3_API分类参考_文件对话框(CategoryDialog) 文件对话框子系统(CategoryDialog) SDL 提供了文件对话框相关接口,允许应用通过系统原生的图形界面让用户选择文件/文件夹——支持「打开文件」「保存文件」「选择文件夹」三种核心场景,还可控制文件过滤规则、是否允许多选等细节。 重要特性 对话框基于系统原生 GUI 实现,视觉风格与操作系统保持一致; 显示对话框是非阻塞操作:调用后立即返回控制权给应用,用户完成选择后(确认/取消),SDL 会调用预设的回调函数(可能在其他线程执行)返回结果。 函数 SDL_ShowOpenFileDialog:显示「打开文件」对话框,支持文件过滤、多选配置,用户选择后触发回调返回选中的文件路径列表 SDL_ShowSaveFileDialog:显示「保存文件」对话框,支持文件过滤,用户确认后触发回调返回保存路径 SDL_ShowOpenFolderDialog:显示「选择文件夹」对话框,用户选择后触发回调返回选中的文件夹路径 SDL_ShowFileDialogWithProperties:显示自定义属性的文件对话框(最灵活的接口),支持指定对话框类型、过滤规则、父窗口、默认路径等所有配置 数据类型 SDL_DialogFileCallback:文件对话框回调函数类型,用户完成选择后触发,参数包含「是否取消」「选中的文件/文件夹路径数组」「自定义用户数据」 结构体 SDL_DialogFileFilter:文件过滤规则结构体,包含过滤器名称(如「图片文件」)和扩展名列表(如「.png;.jpg」) 枚举 SDL_FileDialogType:文件对话框类型枚举,核心取值: SDL_FILEDIALOG_OPEN:打开文件对话框 SDL_FILEDIALOG_SAVE:保存文件对话框 SDL_FILEDIALOG_OPEN_FOLDER:选择文件夹对话框 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充枚举/类型/结构体/函数声明(FreeBASIC 绑定可能缺失) Enum SDL_FileDialogType SDL_FILEDIALOG_OPEN = 0 ' 打开文件 SDL_FILEDIALOG_SAVE = 1 ' 保存文件 SDL_FILEDIALOG_OPEN_FOLDER = 2 ' 选择文件夹 End Enum ' 文件过滤规则结构体 Type SDL_DialogFileFilter name As ZString Ptr ' 过滤器名称(如 "图片文件") patterns As ZString Ptr ' 扩展名模式(如 "*.png;*.jpg;*.bmp") End Type ' 回调函数类型定义:用户完成选择后触发 Type SDL_DialogFileCallback As Sub( _ ByVal cancelled As SDL_bool, _ ByVal file_count As Integer, _ ByVal files As ZString Ptr Ptr, _ ByVal userdata As Any Ptr _ ) ' 核心函数声明 Declare Function SDL_ShowOpenFileDialog CDecl ( _ ByVal parent As SDL_Window Ptr, _ ByVal title As ZString Ptr, _ ByVal default_path As ZString Ptr, _ ByVal filter_count As Integer, _ ByVal filters As SDL_DialogFileFilter Ptr, _ ByVal allow_multiple As SDL_bool, _ ByVal callback As SDL_DialogFileCallback, _ ByVal userdata As Any Ptr _ ) As SDL_bool Declare Function SDL_ShowSaveFileDialog CDecl ( _ ByVal parent As SDL_Window Ptr, _ ByVal title As ZString Ptr, _ ByVal default_path As ZString Ptr, _ ByVal filter_count As Integer, _ ByVal filters As SDL_DialogFileFilter Ptr, _ ByVal callback As SDL_DialogFileCallback, _ ByVal userdata As Any Ptr _ ) As SDL_bool Declare Function SDL_ShowOpenFolderDialog CDecl ( _ ByVal parent As SDL_Window Ptr, _ ByVal title As ZString Ptr, _ ByVal default_path As ZString Ptr, _ ByVal callback As SDL_DialogFileCallback, _ ByVal userdata As Any Ptr _ ) As SDL_bool ' 全局标志:用于主线程等待回调执行完成 Dim Shared As SDL_bool g_dialogCompleted = SDL_FALSE ' 回调函数:处理「打开文件」对话框结果 Sub OpenFileCallback( _ ByVal cancelled As SDL_bool, _ ByVal file_count As Integer, _ ByVal files As ZString Ptr Ptr, _ ByVal userdata As Any Ptr _ ) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【打开文件对话框回调】") If (cancelled = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了文件选择") ElseIf (file_count > 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选中了 %d 个文件:", file_count) For i As Integer = 0 To file_count - 1 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - %s", *files[i]) Next Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未选中任何文件") End If ' 标记对话框操作完成 g_dialogCompleted = SDL_TRUE End Sub ' 回调函数:处理「保存文件」对话框结果 Sub SaveFileCallback( _ ByVal cancelled As SDL_bool, _ ByVal file_count As Integer, _ ByVal files As ZString Ptr Ptr, _ ByVal userdata As Any Ptr _ ) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【保存文件对话框回调】") If (cancelled = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了保存操作") ElseIf (file_count = 1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择的保存路径:%s", *files[0]) ' 模拟保存文件逻辑 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 开始保存文件到指定路径...") End If g_dialogCompleted = SDL_TRUE End Sub ' 回调函数:处理「选择文件夹」对话框结果 Sub OpenFolderCallback( _ ByVal cancelled As SDL_bool, _ ByVal file_count As Integer, _ ByVal files As ZString Ptr Ptr, _ ByVal userdata As Any Ptr _ ) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【选择文件夹对话框回调】") If (cancelled = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了文件夹选择") ElseIf (file_count = 1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选中的文件夹:%s", *files[0]) End If g_dialogCompleted = SDL_TRUE End Sub ' 示例1:显示「打开文件」对话框(带过滤规则、支持多选) Sub ShowOpenFileDialogExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:显示打开文件对话框】") ' 重置完成标志 g_dialogCompleted = SDL_FALSE ' 定义文件过滤规则 Dim As SDL_DialogFileFilter filters(1) ' 过滤器1:图片文件 filters(0).name = StrPtr("图片文件") filters(0).patterns = StrPtr("*.png;*.jpg;*.jpeg;*.bmp") ' 过滤器2:所有文件 filters(1).name = StrPtr("所有文件") filters(1).patterns = StrPtr("*.*") ' 显示「打开文件」对话框 Dim As SDL_bool result = SDL_ShowOpenFileDialog( _ NULL, ' 无父窗口 StrPtr("选择要打开的图片文件"), ' 对话框标题 StrPtr("."), ' 默认路径(当前目录) 2, ' 过滤器数量 @filters(0), ' 过滤器数组 SDL_TRUE, ' 允许选择多个文件 @OpenFileCallback, ' 回调函数 NULL ' 自定义用户数据 ) If (result = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示打开文件对话框失败:%s", SDL_GetError()) Exit Sub End If ' 等待回调执行完成(非阻塞对话框需主动等待,实际应用可结合事件循环) While (g_dialogCompleted = SDL_FALSE) SDL_Delay(100) ' 避免CPU占用过高 Wend End Sub ' 示例2:显示「保存文件」对话框(带过滤规则) Sub ShowSaveFileDialogExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:显示保存文件对话框】") g_dialogCompleted = SDL_FALSE ' 定义保存文件的过滤规则(文本文件) Dim As SDL_DialogFileFilter filter filter.name = StrPtr("文本文件") filter.patterns = StrPtr("*.txt") ' 显示「保存文件」对话框 Dim As SDL_bool result = SDL_ShowSaveFileDialog( _ NULL, ' 无父窗口 StrPtr("保存文本文件"), ' 对话框标题 StrPtr("./untitled.txt"), ' 默认保存路径/文件名 1, ' 过滤器数量 @filter, ' 过滤器 @SaveFileCallback, ' 回调函数 NULL ' 自定义用户数据 ) If (result = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示保存文件对话框失败:%s", SDL_GetError()) Exit Sub End If ' 等待回调执行完成 While (g_dialogCompleted = SDL_FALSE) SDL_Delay(100) Wend End Sub ' 示例3:显示「选择文件夹」对话框 Sub ShowOpenFolderDialogExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:显示选择文件夹对话框】") g_dialogCompleted = SDL_FALSE ' 显示「选择文件夹」对话框 Dim As SDL_bool result = SDL_ShowOpenFolderDialog( _ NULL, ' 无父窗口 StrPtr("选择工作目录"), ' 对话框标题 StrPtr("."), ' 默认路径 @OpenFolderCallback, ' 回调函数 NULL ' 自定义用户数据 ) If (result = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示选择文件夹对话框失败:%s", SDL_GetError()) Exit Sub End If ' 等待回调执行完成 While (g_dialogCompleted = SDL_FALSE) SDL_Delay(100) Wend 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 ' 运行示例 ShowOpenFileDialogExample() ShowSaveFileDialogExample() ShowOpenFolderDialogExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 关键前置条件: 必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),否则对话框无法显示; 回调函数可能在非主线程执行,若需操作 UI/渲染资源,需通过 SDL 事件队列同步到主线程。 文件过滤规则格式: 扩展名模式使用分号 ; 分隔(如 "*.png;*.jpg"); 过滤器名称用于对话框的下拉选择(如「图片文件」「文本文件」); 通配符 *.* 表示所有文件,是通用过滤器。 非阻塞特性处理: 示例中使用 SDL_Delay() + 全局标志等待回调,实际应用中建议: 将标志整合到 SDL 事件循环中; 回调函数中发送自定义 SDL 事件,主线程处理事件时执行后续逻辑; 避免长时间阻塞主线程,保证应用响应性。 平台兼容性: 平台 支持情况 特殊说明 Windows 完全支持(Open/Save/Folder) 原生文件资源管理器样式 macOS 完全支持(Open/Save/Folder) 原生访达(Finder)样式 Linux 完全支持(依赖桌面环境) GTK/KDE 风格,无桌面环境可能降级为终端选择 移动平台 仅部分支持(需适配) Android/iOS 需调用系统文件选择器 总结 核心优势: 跨平台统一的文件对话框接口,无需适配 Windows 的 GetOpenFileName、macOS 的 NSOpenPanel 等原生 API; 非阻塞设计,避免对话框阻塞应用主线程,保证应用响应性; 支持文件过滤、多选、默认路径等实用配置,满足大部分文件操作场景; 基于系统原生 UI,视觉体验与操作系统一致。 使用建议: 简单场景优先使用 SDL_ShowOpenFileDialog/SDL_ShowSaveFileDialog/SDL_ShowOpenFolderDialog; 复杂配置(如指定父窗口、自定义样式)使用 SDL_ShowFileDialogWithProperties; 回调函数中避免直接操作 UI,需同步到主线程; 过滤规则建议包含「所有文件」选项,提升用户灵活性; 处理路径时注意跨平台分隔符(Windows 用 \,Linux/macOS 用 /),可使用 SDL 路径工具函数统一处理。 关键点回顾: 显示文件对话框必须初始化 SDL 视频子系统; 对话框为非阻塞操作,结果通过 SDL_DialogFileCallback 回调返回; SDL_DialogFileFilter 用于设置文件类型过滤规则,扩展名用分号分隔; 回调可能在非主线程执行,需注意线程安全(如 UI 操作、资源访问)。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_消息框(CategoryMessagebox) 2026-3-7
      SDL3_API分类参考_消息框(CategoryMessagebox) 消息框子系统(CategoryMessagebox) SDL 提供了一套简洁的消息框 API,适用于展示轻量提示信息——比如程序启动时发生致命错误(无需搭建完整 UI 即可告知用户),或在自定义 UI 加载完成前向用户展示关键提示。 这些消息框会尽可能使用系统原生对话框样式,保证与操作系统的视觉一致性。 SDL 提供两种消息框接口: 自定义消息框(SDL_ShowMessageBox()):支持丰富的配置选项(如多按钮、自定义颜色、图标类型),并能返回用户的选择结果; 简易消息框(SDL_ShowSimpleMessageBox()):极简接口,仅需传入提示文本和标题,等待用户点击「确定」按钮即可,满足大部分基础提示场景。 函数 SDL_ShowMessageBox:显示自定义样式的消息框,接收 SDL_MessageBoxData 配置结构体,返回用户点击的按钮索引(失败返回非0,可通过 SDL_GetError() 获取错误) SDL_ShowSimpleMessageBox:显示简易消息框,指定消息类型(提示/警告/错误)、标题和内容,无返回值(阻塞至用户点击「确定」) 数据类型 SDL_MessageBoxButtonFlags:消息框按钮标志类型(用于标记默认按钮、退出按钮等,如 SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) SDL_MessageBoxFlags:消息框全局标志类型(用于指定消息框类型/样式,如 SDL_MESSAGEBOX_ERROR/SDL_MESSAGEBOX_WARNING) 结构体 SDL_MessageBoxButtonData:单个按钮的配置结构体,包含按钮标志、按钮索引、按钮文本 SDL_MessageBoxColor:消息框颜色结构体,包含红/绿/蓝(RGB)三个分量(取值 0~255) SDL_MessageBoxColorScheme:消息框配色方案结构体,定义按钮、背景、文本等区域的颜色 SDL_MessageBoxData:自定义消息框的核心配置结构体,包含全局标志、父窗口、标题、内容、按钮数组、配色方案等 枚举 SDL_MessageBoxColorType:消息框颜色类型枚举,标识配色方案中不同区域的颜色,常见值: SDL_MESSAGEBOX_COLOR_BACKGROUND:背景色 SDL_MESSAGEBOX_COLOR_TEXT:文本色 SDL_MESSAGEBOX_COLOR_BUTTON_BORDER:按钮边框色 SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND:按钮背景色 SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED:按钮选中色 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充枚举/类型/结构体声明(FreeBASIC 绑定可能缺失) Enum SDL_MessageBoxFlags SDL_MESSAGEBOX_ERROR = 1 Shl 0 ' 错误类型消息框 SDL_MESSAGEBOX_WARNING = 1 Shl 1 ' 警告类型消息框 SDL_MESSAGEBOX_INFORMATION = 1 Shl 2 ' 信息类型消息框 End Enum Enum SDL_MessageBoxButtonFlags SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 1 Shl 0 ' 回车默认按钮 SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 1 Shl 1 ' ESC 默认按钮 End Enum Enum SDL_MessageBoxColorType SDL_MESSAGEBOX_COLOR_BACKGROUND = 0 ' 背景色 SDL_MESSAGEBOX_COLOR_TEXT = 1 ' 文本色 SDL_MESSAGEBOX_COLOR_BUTTON_BORDER = 2 ' 按钮边框色 SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND = 3 ' 按钮背景色 SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED = 4 ' 按钮选中色 SDL_MESSAGEBOX_COLOR_MAX = 5 ' 颜色类型总数 End Enum Type SDL_MessageBoxColor r As UByte ' 红色分量 (0-255) g As UByte ' 绿色分量 (0-255) b As UByte ' 蓝色分量 (0-255) End Type Type SDL_MessageBoxColorScheme colors(0 To SDL_MESSAGEBOX_COLOR_MAX-1) As SDL_MessageBoxColor End Type Type SDL_MessageBoxButtonData flags As Uint32 ' 按钮标志 buttonid As Integer ' 按钮索引(自定义) text As ZString Ptr ' 按钮文本 End Type Type SDL_MessageBoxData flags As Uint32 ' 消息框全局标志 window As SDL_Window Ptr ' 父窗口(NULL 表示无父窗口) title As ZString Ptr ' 消息框标题 message As ZString Ptr ' 消息框内容 numbuttons As Integer ' 按钮数量 buttons As SDL_MessageBoxButtonData Ptr ' 按钮数组 colorScheme As SDL_MessageBoxColorScheme Ptr ' 配色方案(NULL 使用系统默认) End Type ' 函数声明 Declare Sub SDL_ShowSimpleMessageBox CDecl (ByVal flags As Uint32, ByVal title As ZString Ptr, ByVal message As ZString Ptr, ByVal window As SDL_Window Ptr) Declare Function SDL_ShowMessageBox CDecl (ByVal messageboxdata As SDL_MessageBoxData Ptr, ByRef buttonid As Integer) As Integer ' 示例1:显示简易消息框(提示/警告/错误) Sub ShowSimpleMessageBoxes() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:显示简易消息框】") ' 1. 信息提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示信息提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, _ StrPtr("操作成功"), _ StrPtr("文件已保存至默认路径!"), _ NULL) ' 2. 警告提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示警告提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, _ StrPtr("低电量警告"), _ StrPtr("当前电量不足 20%,请及时充电!"), _ NULL) ' 3. 错误提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示错误提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _ StrPtr("初始化失败"), _ StrPtr("无法加载配置文件,请检查文件是否存在!"), _ NULL) End Sub ' 示例2:显示自定义消息框(多按钮 + 自定义配色) Sub ShowCustomMessageBox() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:显示自定义消息框】") ' 1. 定义按钮(确定/取消/跳过) Dim As SDL_MessageBoxButtonData buttons(2) ' 按钮0:确定(回车默认) buttons(0).flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT buttons(0).buttonid = 0 buttons(0).text = StrPtr("确定") ' 按钮1:取消(ESC 默认) buttons(1).flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT buttons(1).buttonid = 1 buttons(1).text = StrPtr("取消") ' 按钮2:跳过 buttons(2).flags = 0 buttons(2).buttonid = 2 buttons(2).text = StrPtr("跳过") ' 2. 自定义配色方案(可选) Dim As SDL_MessageBoxColorScheme colorScheme ' 背景色:浅灰色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BACKGROUND) = Type<SDL_MessageBoxColor>(240, 240, 240) ' 文本色:黑色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_TEXT) = Type<SDL_MessageBoxColor>(0, 0, 0) ' 按钮背景色:浅蓝色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND) = Type<SDL_MessageBoxColor>(180, 210, 255) ' 按钮选中色:深蓝色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED) = Type<SDL_MessageBoxColor>(100, 140, 255) ' 按钮边框色:灰色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_BORDER) = Type<SDL_MessageBoxColor>(150, 150, 150) ' 3. 配置消息框数据 Dim As SDL_MessageBoxData msgBoxData msgBoxData.flags = SDL_MESSAGEBOX_WARNING ' 警告类型 msgBoxData.window = NULL ' 无父窗口 msgBoxData.title = StrPtr("更新提示") ' 标题 msgBoxData.message = StrPtr("检测到新版本 v2.0,是否立即更新?") ' 内容 msgBoxData.numbuttons = 3 ' 按钮数量 msgBoxData.buttons = @buttons(0) ' 按钮数组 msgBoxData.colorScheme = @colorScheme ' 自定义配色 ' 4. 显示自定义消息框并获取用户选择 Dim As Integer selectedButtonId Dim As Integer result = SDL_ShowMessageBox(@msgBoxData, selectedButtonId) If (result = 0) Then ' 处理用户选择 Select Case selectedButtonId Case 0: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:确定(开始更新)") Case 1: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:取消(放弃更新)") Case 2: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:跳过(稍后更新)") Case Else: SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "用户选择了未知按钮") End Select Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示自定义消息框失败:%s", SDL_GetError()) End If End Sub ' 示例3:带父窗口的消息框(模拟与游戏窗口关联) Sub ShowMessageBoxWithParent() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:带父窗口的消息框】") ' 创建一个临时窗口作为父窗口 Dim As SDL_Window Ptr window = SDL_CreateWindow( _ StrPtr("SDL 示例窗口"), _ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _ 640, 480, _ SDL_WINDOW_SHOWN _ ) If (window <> NULL) Then ' 显示关联父窗口的错误消息框 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _ StrPtr("游戏错误"), _ StrPtr("无法初始化渲染器,请检查显卡驱动!"), _ window) ' 销毁窗口 SDL_DestroyWindow(window) End If 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 ' 运行示例 ShowSimpleMessageBoxes() ShowCustomMessageBox() ShowMessageBoxWithParent() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 关键前置条件: 显示消息框必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),否则会调用失败; 消息框默认是模态对话框,会阻塞当前线程直至用户操作完成。 SDL_MessageBoxFlags 常用值: 标志常量 作用 系统表现 SDL_MESSAGEBOX_ERROR 错误类型 显示错误图标(如 Windows 的红色叉号) SDL_MESSAGEBOX_WARNING 警告类型 显示警告图标(如 Windows 的黄色感叹号) SDL_MESSAGEBOX_INFORMATION 信息类型 显示信息图标(如 Windows 的蓝色i) 按钮标志使用规则: SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT:设置为「回车」快捷键对应的按钮; SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT:设置为「ESC」快捷键对应的按钮; 一个消息框建议仅设置一个回车默认按钮和一个 ESC 默认按钮。 平台兼容性: ✅ Windows/macOS/Linux:完全支持自定义消息框和简易消息框,样式贴合系统原生; ✅ 移动平台(Android/iOS):简易消息框支持良好,自定义消息框会适配移动端样式; ❗ 部分嵌入式系统:可能仅支持简易消息框,自定义配色/多按钮可能失效。 总结 核心优势: 跨平台统一的消息框接口,无需适配不同系统的原生对话框 API(如 Windows 的 MessageBox、GTK 的 gtk_message_dialog); 支持从极简到高度自定义的消息框需求,兼顾易用性和灵活性; 自动适配系统原生样式,保证用户体验一致性; 支持关联父窗口,实现模态对话框的层级关联。 使用建议: 基础提示场景优先使用 SDL_ShowSimpleMessageBox()(代码简洁、兼容性好); 需要用户选择(如确认/取消)时使用 SDL_ShowMessageBox(); 自定义配色仅在特殊需求下使用,优先依赖系统默认配色(更符合用户习惯); 消息框文本建议简洁明了,避免过长内容影响阅读。 关键点回顾: 显示消息框必须初始化 SDL 视频子系统(SDL_INIT_VIDEO); SDL_ShowSimpleMessageBox 适用于单按钮提示,SDL_ShowMessageBox 适用于多按钮选择; 按钮标志可设置回车/ESC 快捷键,提升操作便捷性; 消息框为模态对话框,会阻塞调用线程直至用户操作完成。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_电源管理(CategoryPower) 2026-3-7
      SDL3_API分类参考_电源管理(CategoryPower) 电源管理子系统(CategoryPower) SDL 提供了轻量的电源管理接口,核心功能是获取设备的电源状态信息,尤其适用于移动设备(如笔记本、平板、手机)上的游戏/应用开发。 该子系统仅包含一个核心函数:SDL_GetPowerInfo()。 典型应用场景 检测设备是否使用电池供电,若电池电量低,可降低游戏帧率、关闭特效以减少功耗,延长续航; 全屏运行时显示电池电量指示器; 电量极低时提醒用户保存游戏进度,避免数据丢失。 函数 SDL_GetPowerInfo:获取系统电源状态信息,返回 SDL_PowerState 枚举值;同时通过输出参数返回「剩余电池使用时间(秒)」和「电池电量百分比」(不支持的平台/设备返回对应无效值) 数据类型 (无) 结构体 (无) 枚举 SDL_PowerState:电源状态枚举,包含以下取值: SDL_POWERSTATE_UNKNOWN:无法确定电源状态(如无电池的台式机、不支持的系统) SDL_POWERSTATE_ON_BATTERY:设备正在使用电池供电(未插电) SDL_POWERSTATE_NO_BATTERY:设备无电池(如台式机) SDL_POWERSTATE_CHARGING:电池正在充电 SDL_POWERSTATE_CHARGED:电池已充满电 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充枚举和函数声明(FreeBASIC 绑定可能缺失) Enum SDL_PowerState SDL_POWERSTATE_UNKNOWN = 0 ' 未知状态 SDL_POWERSTATE_ON_BATTERY = 1 ' 电池供电 SDL_POWERSTATE_NO_BATTERY = 2 ' 无电池 SDL_POWERSTATE_CHARGING = 3 ' 充电中 SDL_POWERSTATE_CHARGED = 4 ' 已充满 End Enum Declare Function SDL_GetPowerInfo CDecl (ByRef seconds As Integer, ByRef percent As Integer) As SDL_PowerState ' 转换电源状态枚举为可读字符串 Function PowerStateToString(ByVal state As SDL_PowerState) As ZString Ptr Select Case state Case SDL_POWERSTATE_UNKNOWN: Return StrPtr("未知状态") Case SDL_POWERSTATE_ON_BATTERY: Return StrPtr("电池供电(未插电)") Case SDL_POWERSTATE_NO_BATTERY: Return StrPtr("无电池(台式机等)") Case SDL_POWERSTATE_CHARGING: Return StrPtr("充电中") Case SDL_POWERSTATE_CHARGED: Return StrPtr("电池已充满") Case Else: Return StrPtr("无效状态") End Select End Function ' 获取并打印电源信息 Sub PrintPowerInfo() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【当前电源状态信息】") ' 定义输出参数:剩余使用时间(秒)、电量百分比 Dim As Integer remainingSeconds, batteryPercent Dim As SDL_PowerState powerState = SDL_GetPowerInfo(remainingSeconds, batteryPercent) ' 打印电源状态 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电源状态:%s", *PowerStateToString(powerState)) ' 打印剩余时间(-1 表示无法获取) If (remainingSeconds = -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:无法获取") ElseIf (remainingSeconds = -2) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:无限(插电状态)") Else Dim As Integer hours = remainingSeconds \ 3600 Dim As Integer minutes = (remainingSeconds Mod 3600) \ 60 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:%d小时%d分钟", hours, minutes) End If ' 打印电量百分比(-1 表示无法获取) If (batteryPercent = -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电池电量:无法获取") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电池电量:%d%%", batteryPercent) End If End Sub ' 根据电源状态调整应用配置(节能逻辑) Sub AdjustAppForPower() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据电源状态调整应用配置】") Dim As Integer remainingSeconds, batteryPercent Dim As SDL_PowerState powerState = SDL_GetPowerInfo(remainingSeconds, batteryPercent) ' 仅在电池供电时执行节能逻辑 If (powerState = SDL_POWERSTATE_ON_BATTERY) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "当前为电池供电模式,执行节能策略") ' 电量 > 50%:正常运行 If (batteryPercent > 50 And batteryPercent <> -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量充足(%d%%):保持默认配置", batteryPercent) ' 电量 20% ~ 50%:降低帧率 ElseIf (batteryPercent >= 20 And batteryPercent <= 50) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量中等(%d%%):帧率降低至 30 FPS", batteryPercent) ' 模拟设置帧率 ' SDL_SetWindowDisplayMode(window, &displayMode); ' displayMode.refresh_rate = 30; ' 电量 < 20%:深度节能 ElseIf (batteryPercent > 0 And batteryPercent < 20) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量低(%d%%):关闭特效 + 帧率降至 15 FPS", batteryPercent) ' 模拟关闭特效 ' DisableSpecialEffects(); ' 电量极低(< 10%):提醒保存 ElseIf (batteryPercent > 0 And batteryPercent < 10) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "电量极低(%d%%):请立即保存数据!", batteryPercent) End If Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "当前为插电/无电池模式:使用高性能配置") End If End Sub ' 定时监控电源状态(模拟实时检测) Sub MonitorPowerState() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【实时监控电源状态(5秒)】") Const MONITOR_DURATION As Integer = 5 ' 监控5秒 Const CHECK_INTERVAL As Integer = 1000 ' 每秒检测一次 For i As Integer = 1 To MONITOR_DURATION SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "=== 第 %d 秒检测 ===", i) PrintPowerInfo() SDL_Delay(CHECK_INTERVAL) Next SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "监控结束") 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 ' 运行示例 PrintPowerInfo() AdjustAppForPower() MonitorPowerState() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 SDL_GetPowerInfo 返回值规则: 输出参数 无效值 含义说明 remainingSeconds -1 无法获取剩余时间(如设备不支持) remainingSeconds -2 剩余时间无限(设备插电、无电池) batteryPercent -1 无法获取电量百分比(如设备不支持、无电池) 平台支持说明: ✅ Windows/macOS/Linux:支持大部分笔记本/移动设备的电源状态检测; ✅ 移动平台(Android/iOS):完善支持电池状态、剩余时间、电量百分比; ❌ 无电池设备(台式机、服务器):返回 SDL_POWERSTATE_NO_BATTERY,电量/时间参数返回 -1; ❌ 部分嵌入式系统:可能返回 SDL_POWERSTATE_UNKNOWN(无电源管理接口)。 节能策略设计建议: 电量区间 建议操作 > 50% 高性能模式(满帧率、全特效) 20%~50% 平衡模式(降低帧率至 30 FPS、关闭部分特效) 10%~20% 节能模式(帧率降至 15 FPS、关闭所有特效) < 10% 紧急模式(提醒保存、暂停非核心功能) 调用频率建议: 无需高频调用(电源状态变化缓慢),建议 1~5 秒检测一次即可; 避免在游戏主循环中每帧调用,减少系统开销。 总结 核心优势: 跨平台统一的电源状态检测接口,无需适配不同系统的原生电源 API(如 Windows 的 GetSystemPowerStatus、Android 的 BatteryManager); 轻量易用,仅一个核心函数即可获取电源状态、剩余时间、电量百分比; 返回值规则清晰,边界条件(如无效值)处理明确,便于容错。 使用建议: 移动应用/游戏必须接入电源状态检测,根据电量动态调整性能配置,提升用户体验; 对返回的无效值(-1/-2)做好容错处理,避免程序崩溃; 电量极低时优先提醒用户保存数据,再执行节能逻辑; 插电状态下恢复高性能配置,保证体验。 关键点回顾: SDL_GetPowerInfo 是电源管理的核心函数,返回电源状态枚举,同时输出剩余时间和电量百分比; 仅 SDL_POWERSTATE_ON_BATTERY 状态下需要执行节能逻辑,其他状态可使用高性能配置; 无效值(-1/-2)需特殊处理,避免数值异常导致的逻辑错误; 检测频率建议 1~5 秒一次,无需高频调用。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_进程控制(CategoryProcess) 2026-3-7
      SDL3_API分类参考_进程控制(CategoryProcess) 进程控制子系统(CategoryProcess) SDL 提供了一套跨平台的进程控制接口,用于创建、管理和销毁操作系统级别的子进程,无需适配不同系统的原生进程 API(如 Windows 的 CreateProcess、Linux 的 fork/exec)。 核心使用流程 创建进程:通过 SDL_CreateProcess() 创建基础子进程,或通过 SDL_CreateProcessWithProperties() 创建带高级属性(如 IO 重定向、进程链)的子进程; 进程交互:使用 SDL_ReadProcess()、SDL_GetProcessInput()/SDL_GetProcessOutput() 读写子进程的输入/输出流; 进程管理:通过 SDL_WaitProcess() 获取进程退出状态,或用 SDL_KillProcess() 强制终止进程; 资源清理:无论进程是被杀死、自行退出还是仍在运行,都必须调用 SDL_DestroyProcess() 释放进程相关资源。 函数 SDL_CreateProcess:创建基础子进程,指定可执行文件路径和命令行参数,返回 SDL_Process 句柄(失败返回 NULL,可通过 SDL_GetError() 获取错误) SDL_CreateProcessWithProperties:创建带自定义属性的子进程(支持 IO 重定向、工作目录、环境变量等高级配置),返回 SDL_Process 句柄 SDL_DestroyProcess:销毁进程句柄,释放所有关联资源(即使进程仍在运行,也需调用此函数清理;不会自动终止进程) SDL_GetProcessInput:获取子进程的标准输入(stdin)流句柄,用于向子进程写入数据 SDL_GetProcessOutput:获取子进程的标准输出(stdout)或标准错误(stderr)流句柄,用于读取子进程输出 SDL_GetProcessProperties:获取已创建进程的属性信息(如 IO 配置、进程 ID、工作目录等) SDL_KillProcess:强制终止指定的子进程(向进程发送终止信号,不同系统实现不同:Windows 用 TerminateProcess,Linux/macOS 用 kill) SDL_ReadProcess:简化版子进程输出读取函数,直接从子进程标准输出读取指定长度的数据 SDL_WaitProcess:阻塞等待子进程退出,返回进程的退出码;若进程已退出,立即返回结果 数据类型 SDL_Process:进程句柄类型(封装了平台相关的进程信息,如 Windows 的 HANDLE、Linux 的 pid_t),用于标识和管理子进程 结构体 (无) 枚举 SDL_ProcessIO:进程 IO 配置枚举,用于指定子进程的输入/输出流模式,常见值: SDL_PROCESS_IO_INHERIT:继承父进程的 IO 流(默认) SDL_PROCESS_IO_PIPE:创建管道用于父子进程间 IO 通信 SDL_PROCESS_IO_NULL:重定向到空设备(忽略输入/输出) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充类型和函数声明(FreeBASIC 绑定可能缺失) Type SDL_Process As Any Ptr ' SDL_ProcessIO 枚举定义 Enum SDL_ProcessIO SDL_PROCESS_IO_INHERIT = 0 ' 继承父进程IO SDL_PROCESS_IO_PIPE = 1 ' 创建管道通信 SDL_PROCESS_IO_NULL = 2 ' 重定向到空设备 End Enum ' 进程属性结构体(简化版,实际 SDL 定义更完整) Type SDL_ProcessProperties io_stdin As SDL_ProcessIO ' 标准输入配置 io_stdout As SDL_ProcessIO ' 标准输出配置 io_stderr As SDL_ProcessIO ' 标准错误配置 working_directory As ZString Ptr ' 工作目录 environment As ZString Ptr Ptr ' 环境变量 End Type ' 核心函数声明 Declare Function SDL_CreateProcess CDecl (ByVal path As ZString Ptr, ByVal args As ZString Ptr Ptr) As SDL_Process Declare Function SDL_CreateProcessWithProperties CDecl (ByVal path As ZString Ptr, ByVal args As ZString Ptr Ptr, ByVal props As SDL_ProcessProperties Ptr) As SDL_Process Declare Sub SDL_DestroyProcess CDecl (ByVal process As SDL_Process) Declare Function SDL_GetProcessInput CDecl (ByVal process As SDL_Process) As SDL_IOStream Ptr Declare Function SDL_GetProcessOutput CDecl (ByVal process As SDL_Process) As SDL_IOStream Ptr Declare Function SDL_GetProcessProperties CDecl (ByVal process As SDL_Process, ByVal props As SDL_ProcessProperties Ptr) As Integer Declare Function SDL_KillProcess CDecl (ByVal process As SDL_Process) As Integer Declare Function SDL_ReadProcess CDecl (ByVal process As SDL_Process, ByVal buffer As Any Ptr, ByVal size As Integer) As Integer Declare Function SDL_WaitProcess CDecl (ByVal process As SDL_Process, ByRef exit_code As Integer) As Integer ' 示例1:创建基础子进程并读取输出 Sub CreateBasicProcess() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:创建基础子进程】") ' 定义命令行参数(根据平台适配) Dim As ZString Ptr args(2) #If Defined(SDL_PLATFORM_WINDOWS) ' Windows:执行 cmd /c echo 测试内容 Dim As ZString * 256 exePath = "cmd.exe" args(0) = StrPtr("/c") args(1) = StrPtr("echo Hello from child process (Windows)!") args(2) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS:执行 echo 测试内容 Dim As ZString * 256 exePath = "/bin/echo" args(0) = StrPtr("Hello from child process (Linux/macOS)!") args(1) = NULL #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "不支持的平台") Exit Sub #EndIf ' 创建子进程 Dim As SDL_Process proc = SDL_CreateProcess(@exePath, @args(0)) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建进程失败:%s", SDL_GetError()) Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程创建成功") ' 读取子进程输出 Dim As UByte buffer(1023) Dim As Integer readSize = SDL_ReadProcess(proc, @buffer(0), 1024) If (readSize > 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程输出:%.*s", readSize, @buffer(0)) ElseIf (readSize = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "子进程无输出") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "读取子进程输出失败:%s", SDL_GetError()) End If ' 等待进程退出并获取退出码 Dim As Integer exitCode If (SDL_WaitProcess(proc, exitCode) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程正常退出,退出码:%d", exitCode) Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "等待进程退出失败:%s", SDL_GetError()) End If ' 销毁进程句柄(必须调用) SDL_DestroyProcess(proc) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "进程句柄已销毁") End Sub ' 示例2:创建带属性的进程(IO 重定向 + 自定义工作目录) Sub CreateProcessWithProps() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:创建带属性的子进程】") ' 配置进程属性 Dim As SDL_ProcessProperties props props.io_stdin = SDL_PROCESS_IO_NULL ' 标准输入重定向到空 props.io_stdout = SDL_PROCESS_IO_PIPE ' 标准输出创建管道 props.io_stderr = SDL_PROCESS_IO_PIPE ' 标准错误创建管道 props.working_directory = StrPtr(".") ' 工作目录为当前目录 props.environment = NULL ' 继承父进程环境变量 ' 定义命令(执行目录列表命令) Dim As ZString Ptr args(1) Dim As ZString * 256 exePath #If Defined(SDL_PLATFORM_WINDOWS) exePath = "cmd.exe" args(0) = StrPtr("/c dir") args(1) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) exePath = "/bin/ls" args(0) = StrPtr("-l") args(1) = NULL #Else Exit Sub #EndIf ' 创建带属性的进程 Dim As SDL_Process proc = SDL_CreateProcessWithProperties(@exePath, @args(0), @props) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建带属性进程失败:%s", SDL_GetError()) Exit Sub End If ' 等待进程完成 Dim As Integer exitCode SDL_WaitProcess(proc, exitCode) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "带属性进程退出码:%d", exitCode) ' 销毁进程句柄 SDL_DestroyProcess(proc) End Sub ' 示例3:强制终止长时间运行的进程 Sub KillLongRunningProcess() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:强制终止子进程】") ' 创建一个长时间运行的进程 Dim As ZString Ptr args(1) Dim As ZString * 256 exePath #If Defined(SDL_PLATFORM_WINDOWS) ' Windows:执行 timeout 10(等待10秒) exePath = "timeout.exe" args(0) = StrPtr("10") args(1) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS:执行 sleep 10(等待10秒) exePath = "/bin/sleep" args(0) = StrPtr("10") args(1) = NULL #Else Exit Sub #EndIf Dim As SDL_Process proc = SDL_CreateProcess(@exePath, @args(0)) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建进程失败:%s", SDL_GetError()) Exit Sub End If ' 等待2秒后强制终止 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "等待2秒后终止进程...") SDL_Delay(2000) If (SDL_KillProcess(proc) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "进程已强制终止") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "终止进程失败:%s", SDL_GetError()) End If ' 等待进程退出(确认终止) Dim As Integer exitCode SDL_WaitProcess(proc, exitCode) ' 销毁进程句柄 SDL_DestroyProcess(proc) 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 ' 运行示例 CreateBasicProcess() CreateProcessWithProps() KillLongRunningProcess() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 跨平台进程创建差异: 平台 原生进程 API SDL 封装优势 Windows CreateProcess 无需处理 STARTUPINFO/PROCESS_INFORMATION 结构体 Linux fork + execve 无需手动处理子进程 fork 后的资源隔离 macOS fork + execvp 统一的错误处理和资源清理逻辑 SDL_ProcessIO 枚举使用场景: SDL_PROCESS_IO_INHERIT:子进程直接使用父进程的控制台/终端(适合简单命令执行); SDL_PROCESS_IO_PIPE:父子进程通过管道通信(适合需要读取/写入子进程输出/输入的场景); SDL_PROCESS_IO_NULL:忽略子进程的 IO(适合后台运行、无需交互的进程)。 关键注意事项: 资源清理:无论进程状态如何,必须调用 SDL_DestroyProcess(),否则会导致资源泄漏; 阻塞等待:SDL_WaitProcess() 是阻塞函数,若需非阻塞检测进程状态,可先调用 SDL_KillProcess() 或结合 SDL 事件循环; 权限问题:创建进程时需确保可执行文件路径有执行权限,工作目录有访问权限; 参数传递:命令行参数数组必须以 NULL 结尾(符合 C 语言参数传递规范)。 错误处理建议: 所有进程创建/操作函数失败时返回 NULL/非0,需通过 SDL_GetError() 获取具体错误信息; 对长时间运行的进程,建议增加超时逻辑(如 SDL_Delay() + SDL_KillProcess()); 读取子进程输出时,缓冲区大小需合理(避免溢出或截断)。 总结 核心优势: 跨平台统一的进程控制接口,无需适配不同系统的原生进程 API; 简化的 IO 重定向配置(通过 SDL_ProcessIO 枚举),无需手动创建管道/文件句柄; 完善的资源管理机制,SDL_DestroyProcess() 统一清理进程相关资源; 兼容主流平台的进程终止、等待逻辑,降低跨平台开发成本。 使用建议: 简单进程创建优先使用 SDL_CreateProcess(),需要高级配置时使用 SDL_CreateProcessWithProperties(); 读取子进程输出时,优先使用 SDL_ReadProcess()(简化接口),复杂 IO 交互使用 SDL_GetProcessOutput() 获取流句柄; 强制终止进程前,建议先尝试优雅退出(如向子进程发送信号),仅在必要时使用 SDL_KillProcess(); 始终在进程使用完毕后调用 SDL_DestroyProcess(),即使进程已退出。 关键点回顾: SDL_Process 是进程句柄核心类型,所有进程操作均基于此句柄; SDL_DestroyProcess() 必须调用,是避免资源泄漏的关键; SDL_ProcessIO 枚举控制进程 IO 模式,SDL_PROCESS_IO_PIPE 是父子进程通信的核心配置; SDL_WaitProcess() 阻塞等待进程退出,SDL_KillProcess() 强制终止进程,需配合使用以保证进程状态可控。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_共享对象(CategorySharedObject) 2026-3-7
      SDL3_API分类参考_共享对象(CategorySharedObject) 共享对象子系统(CategorySharedObject) SDL 提供了一套与系统无关的共享库加载接口,用于在运行时动态加载可执行代码模块——这类模块在不同系统中有不同的称呼:Windows 下称为「DLL」,Linux 下称为「共享库(.so)」,macOS 下称为「动态库(.dylib)」等。 使用流程: 编译生成共享库文件; 调用 SDL_LoadObject() 加载该共享库; 通过 SDL_LoadFunction() 从加载的共享库中查找并获取导出符号(函数)的地址; 使用完毕后,调用 SDL_UnloadObject() 卸载共享库并释放资源。 注意事项 这些函数仅支持 C 风格函数名:其他语言(如 C++)的函数名会发生「名字改编(name mangling)」,且不同编译器的处理方式不同,无法直接加载; 函数指针调用约定需匹配:声明的函数指针必须与共享库中实际函数的调用约定(如 cdecl、stdcall)一致,否则程序会莫名崩溃; 避免命名空间冲突:从共享库加载的符号是否进入应用全局命名空间是未定义行为,若与代码或其他共享库的符号冲突,会导致预期外的结果; 卸载后指针失效:共享库卸载后,所有通过 SDL_LoadFunction() 获取的函数指针都会失效(即使后续重新加载该库);若计划后续使用这些指针,请勿卸载库(尤其注意不要将这类指针传给 atexit(),可能导致库卸载后调用失效指针)。 函数 SDL_LoadObject:加载指定路径的共享库(DLL/.so/.dylib),返回 SDL_SharedObject 句柄(加载失败返回 NULL,可通过 SDL_GetError() 获取错误信息) SDL_LoadFunction:从已加载的共享库中查找指定名称的导出函数,返回函数指针(查找失败返回 NULL) SDL_UnloadObject:卸载已加载的共享库,释放相关资源(传入 NULL 无操作) 数据类型 SDL_SharedObject:共享库句柄类型(本质是平台相关的指针类型,用于标识已加载的共享库) 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充类型和函数声明(FreeBASIC 绑定可能缺失) Type SDL_SharedObject As Any Ptr Declare Function SDL_LoadObject CDecl (ByVal path As ZString Ptr) As SDL_SharedObject Declare Function SDL_LoadFunction CDecl (ByVal so_handle As SDL_SharedObject, ByVal name As ZString Ptr) As Any Ptr Declare Sub SDL_UnloadObject CDecl (ByVal so_handle As SDL_SharedObject) ' 定义共享库中导出函数的指针类型(需与实际函数签名一致) ' 示例1:无参数无返回值的函数 Type FuncVoid_Void As Sub() ' 示例2:int 参数 + int 返回值的函数 Type FuncInt_Int As Function(ByVal value As Integer) As Integer ' 示例3:字符串参数 + 字符串返回值的函数 Type FuncStr_Str As Function(ByVal str As ZString Ptr) As ZString Ptr ' 加载共享库并调用导出函数 Sub LoadAndCallSharedLib() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【加载并调用共享库】") ' 1. 定义共享库路径(根据平台适配) Dim As ZString * 256 libPath #If Defined(SDL_PLATFORM_WINDOWS) libPath = "mylib.dll" ' Windows 下的 DLL 路径 #Elif Defined(SDL_PLATFORM_LINUX) libPath = "./libmylib.so" ' Linux 下的共享库路径 #Elif Defined(SDL_PLATFORM_MACOS) libPath = "./libmylib.dylib" ' macOS 下的动态库路径 #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "不支持的平台") Exit Sub #EndIf ' 2. 加载共享库 Dim As SDL_SharedObject libHandle = SDL_LoadObject(@libPath) If (libHandle = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载共享库失败:%s", SDL_GetError()) Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "共享库 %s 加载成功", libPath) ' 3. 查找并调用第一个导出函数:void HelloWorld() Dim As Any Ptr funcPtr1 = SDL_LoadFunction(libHandle, StrPtr("HelloWorld")) If (funcPtr1 = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未找到函数 HelloWorld:%s", SDL_GetError()) Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "调用 HelloWorld():") Dim As FuncVoid_Void helloFunc = Cast(FuncVoid_Void, funcPtr1) helloFunc() ' 调用共享库中的函数 End If ' 4. 查找并调用第二个导出函数:int Add(int a) Dim As Any Ptr funcPtr2 = SDL_LoadFunction(libHandle, StrPtr("Add")) If (funcPtr2 = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未找到函数 Add:%s", SDL_GetError()) Else Dim As FuncInt_Int addFunc = Cast(FuncInt_Int, funcPtr2) Dim As Integer result = addFunc(100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "调用 Add(100) → 结果:%d", result) End If ' 5. 查找并调用第三个导出函数:char* Greet(char* name) Dim As Any Ptr funcPtr3 = SDL_LoadFunction(libHandle, StrPtr("Greet")) If (funcPtr3 = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未找到函数 Greet:%s", SDL_GetError()) Else Dim As FuncStr_Str greetFunc = Cast(FuncStr_Str, funcPtr3) Dim As ZString Ptr greetResult = greetFunc(StrPtr("SDL 用户")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "调用 Greet(""SDL 用户"") → 结果:%s", *greetResult) End If ' 6. 卸载共享库(注意:卸载后所有函数指针失效) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "卸载共享库 %s", libPath) SDL_UnloadObject(libHandle) ' 测试:卸载后调用函数指针(会导致崩溃,此处仅作警示) ' If (funcPtr1 <> NULL) Then ' Dim As FuncVoid_Void helloFunc = Cast(FuncVoid_Void, funcPtr1) ' helloFunc() ' 危险:指针已失效! ' End If End Sub ' 演示:处理加载失败的情况(容错逻辑) Sub HandleLoadFailure() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【共享库加载容错处理】") ' 尝试加载不存在的库 Dim As SDL_SharedObject libHandle = SDL_LoadObject(StrPtr("nonexistent_lib.dll")) If (libHandle = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "加载不存在的库失败(预期行为):%s", SDL_GetError()) ' 容错逻辑:使用内置实现替代 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "使用内置替代函数:") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "HelloWorld (内置):你好,这是内置实现!") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Add(100) (内置) → 结果:%d", 100 + 50) Else SDL_UnloadObject(libHandle) End If End Sub ' 共享库开发示例(供参考:编译为共享库的代码) ' 以下代码需单独编译为 DLL/.so/.dylib,示例中仅作注释说明 ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' mylib.c (C 语言共享库源码) ' #include <stdio.h> ' #include <string.h> ' ' // 导出函数1:无参数无返回值 ' __declspec(dllexport) void HelloWorld() { ' printf("Hello from shared library!\n"); ' } ' ' // 导出函数2:int 参数 + int 返回值 ' __declspec(dllexport) int Add(int a) { ' return a + 50; ' } ' ' // 导出函数3:字符串参数 + 字符串返回值 ' __declspec(dllexport) char* Greet(char* name) { ' static char buffer[100]; ' snprintf(buffer, sizeof(buffer), "你好,%s!", name); ' return buffer; ' } ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' 主程序 Sub Main() ' 初始化 SDL If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 LoadAndCallSharedLib() HandleLoadFailure() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 平台适配要点: 平台 共享库后缀 加载路径规则 编译共享库的关键参数 Windows .dll 优先查找当前目录,再查找系统路径 MinGW: -shared -o mylib.dll Linux .so 需指定绝对路径或 LD_LIBRARY_PATH GCC: -shared -fPIC -o libmylib.so macOS .dylib 需指定绝对路径或 @rpath Clang: -shared -fPIC -o libmylib.dylib 函数导出规则: C 语言函数默认可导出(Windows 需加 __declspec(dllexport),Linux/macOS 无需额外修饰); C++ 函数需用 extern "C" 避免名字改编,否则无法通过原函数名查找; 函数调用约定需统一(如 Windows 下 DLL 函数常用 stdcall,需在函数指针声明时匹配)。 常见错误及解决: 加载库失败:检查路径是否正确、库文件是否存在、库依赖是否完整(Windows 可通过 Dependency Walker 检查,Linux 用 ldd,macOS 用 otool -L); 查找函数失败:检查函数名是否正确(区分大小写)、是否导出、C++ 函数是否加 extern "C"; 调用函数崩溃:检查函数指针类型/调用约定是否匹配、参数个数/类型是否一致。 内存管理注意: 共享库内部分配的内存,需由库自身提供释放函数(避免跨库内存管理导致崩溃); 不要将共享库中的静态变量指针返回给主程序后卸载库(静态变量会随库卸载失效)。 总结 核心优势: 跨平台统一的共享库加载接口,无需适配 Windows/Linux/macOS 的原生 API(如 LoadLibrary/dlopen); 简化动态插件系统开发,支持运行时加载/卸载功能模块; 完善的错误处理机制,可通过 SDL_GetError() 获取详细的加载/查找失败原因。 使用建议: 优先加载 C 风格导出函数,避免 C++ 名字改编问题; 声明函数指针时严格匹配原函数的参数、返回值和调用约定; 实现容错逻辑:共享库加载/查找失败时,使用内置替代函数保证程序可用; 避免频繁加载/卸载共享库,卸载前确保所有函数指针不再使用; 共享库路径优先使用绝对路径,避免平台相关的路径查找问题。 关键点回顾: SDL_LoadObject 加载共享库返回句柄,失败返回 NULL;SDL_LoadFunction 查找函数返回指针,失败返回 NULL; 共享库卸载后,所有通过 SDL_LoadFunction 获取的指针立即失效,禁止调用; 仅支持 C 风格函数名,C++ 函数需加 extern "C" 避免名字改编; 函数调用约定必须匹配,否则会导致程序崩溃。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_位操作(CategoryBits) 2026-3-7
      SDL3_API分类参考_位操作(CategoryBits) 位操作子系统(CategoryBits) SDL 提供了用于操作二进制位和位掩码的工具函数,简化常见的位运算逻辑实现。 函数 SDL_HasExactlyOneBitSet32:检测 32 位无符号整数中是否恰好只有 1 个位被置 1(返回非 0 表示是,0 表示否;0 值返回 0) SDL_MostSignificantBitIndex32:获取 32 位无符号整数中最高有效位(最左侧置 1 的位)的索引(如 0x80000000 返回 31,0x00000001 返回 0,0 值返回 -1) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_HasExactlyOneBitSet32 CDecl (ByVal x As UInteger) As Integer Declare Function SDL_MostSignificantBitIndex32 CDecl (ByVal x As UInteger) As Integer ' 示例1:检测是否为2的幂(恰好1个位置1) Sub CheckPowerOfTwo() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:检测2的幂】") ' 测试用例:2的幂、非2的幂、0值 Dim As UInteger testValues(5) = {1, 2, 4, 8, 6, 0} For i As Integer = 0 To UBound(testValues) Dim As UInteger value = testValues(i) Dim As Integer isPowerOfTwo = SDL_HasExactlyOneBitSet32(value) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, _ "数值 0x%08X (%d):%s2的幂", _ value, value, IIf(isPowerOfTwo, "是", "不是")) Next End Sub ' 示例2:获取最高有效位索引 Sub GetMSBIndex() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:获取最高有效位索引】") ' 测试用例:不同位置的置1位、0值 Dim As UInteger testValues(6) = { _ &H00000001, ' 第0位 → 索引0 &H00000080, ' 第7位 → 索引7 &H00008000, ' 第15位 → 索引15 &H00800000, ' 第23位 → 索引23 &H80000000, ' 第31位 → 索引31 &H12345678, ' 混合位 → 最高位28 0 ' 0值 → 索引-1 } For i As Integer = 0 To UBound(testValues) Dim As UInteger value = testValues(i) Dim As Integer msbIndex = SDL_MostSignificantBitIndex32(value) If (msbIndex = -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "数值 0x%08X:无有效位(索引-1)", value) Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, _ "数值 0x%08X:最高有效位索引 = %d(对应2^%d = %d)", _ value, msbIndex, msbIndex, 1 Shl msbIndex) End If Next End Sub ' 示例3:位掩码有效性检测 Sub ValidateBitmask() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:位掩码有效性检测】") ' 场景:某功能仅允许单个标志位(而非组合位),需检测输入是否合法 Enum FeatureFlags FLAG_A = 1 Shl 0 ' 0x00000001 FLAG_B = 1 Shl 1 ' 0x00000002 FLAG_C = 1 Shl 2 ' 0x00000004 FLAG_D = 1 Shl 3 ' 0x00000008 End Enum ' 测试输入:合法(单标志)、非法(多标志)、0值 Dim As UInteger inputs(3) = {FLAG_A, FLAG_B Or FLAG_C, FLAG_D, 0} For i As Integer = 0 To UBound(inputs) Dim As UInteger input = inputs(i) Dim As Integer isValid = SDL_HasExactlyOneBitSet32(input) If (input = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "输入掩码 0x%08X:空值(无功能选中)", input) ElseIf (isValid) Then Dim As Integer flagIndex = SDL_MostSignificantBitIndex32(input) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, _ "输入掩码 0x%08X:合法(单标志位,索引%d)", input, flagIndex) Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, _ "输入掩码 0x%08X:非法(多个标志位同时选中)", input) End If Next End Sub ' 示例4:性能对比(SDL函数 vs 手动实现) Sub PerformanceComparison() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例4:性能对比】") Const TEST_COUNT As ULongInt = 100000000 ' 1亿次调用 Dim As UInteger testValue = &H12345678 Dim As ULongInt startTicks, endTicks Dim As Double elapsed ' 测试 SDL_MostSignificantBitIndex32 startTicks = SDL_GetPerformanceCounter() For i As ULongInt = 1 To TEST_COUNT Dim As Integer idx = SDL_MostSignificantBitIndex32(testValue) Next endTicks = SDL_GetPerformanceCounter() elapsed = (endTicks - startTicks) / SDL_GetPerformanceFrequency() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, _ "SDL_MostSignificantBitIndex32 执行%llu次耗时:%.3f秒", TEST_COUNT, elapsed) ' 测试手动实现的最高有效位查找 startTicks = SDL_GetPerformanceCounter() For i As ULongInt = 1 To TEST_COUNT Dim As Integer idx = -1 Dim As UInteger val = testValue If (val <> 0) Then For j As Integer = 31 DownTo 0 If (val And (1 Shl j)) Then idx = j Exit For End If Next End If Next endTicks = SDL_GetPerformanceCounter() elapsed = (endTicks - startTicks) / SDL_GetPerformanceFrequency() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, _ "手动实现 执行%llu次耗时:%.3f秒", TEST_COUNT, elapsed) 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 ' 运行示例 CheckPowerOfTwo() GetMSBIndex() ValidateBitmask() PerformanceComparison() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 位操作函数的实现原理: SDL_HasExactlyOneBitSet32:利用位运算特性 x & (x - 1) == 0(仅当 x 是 2 的幂时成立),同时排除 x=0 的情况; SDL_MostSignificantBitIndex32:底层使用 CPU 指令(如 x86 的 bsr、ARM 的 clz)实现,比手动循环查找快数十倍。 函数返回值规则: 函数 输入值 返回值 说明 SDL_HasExactlyOneBitSet32 0 0 无置 1 位,不是 2 的幂 SDL_HasExactlyOneBitSet32 1 (0x00000001) 非0 恰好 1 位,是 2 的幂 SDL_HasExactlyOneBitSet32 6 (0x00000110) 0 多个位置 1,不是 2 的幂 SDL_MostSignificantBitIndex32 0 -1 无有效位 SDL_MostSignificantBitIndex32 8 (0x00001000) 3 最高位是第 3 位 典型应用场景: 2 的幂检测:内存分配、缓冲区大小校验(如纹理尺寸需为 2 的幂); 最高有效位查找:快速计算数值的二进制位数、动态调整位掩码范围; 单标志位校验:确保输入的位掩码仅包含一个功能标志(避免多标志冲突)。 性能优势: SDL 位操作函数基于 CPU 专用指令实现,比手动循环/位运算快 10~100 倍; 内联实现无函数调用开销,适合高频调用场景(如图形渲染、数据压缩)。 总结 核心优势: 封装底层 CPU 位操作指令,无需开发者关注架构差异; 提供语义清晰的函数接口,避免手写易出错的位运算逻辑; 极致的执行性能,远超手动实现的位操作代码; 返回值规则明确,边界条件(如 0 值)处理完善。 使用建议: 检测 2 的幂时,优先使用 SDL_HasExactlyOneBitSet32 而非手写 x & (x-1) == 0(已处理 x=0 边界); 查找最高有效位时,必须使用 SDL_MostSignificantBitIndex32(性能和兼容性最优); 位掩码校验场景中,用 SDL_HasExactlyOneBitSet32 确保输入仅含单个标志位; 64 位数值可通过拆分高位/低位,结合 32 位函数实现类似功能。 关键点回顾: SDL_HasExactlyOneBitSet32 是检测「2 的幂」的最优方式,返回非 0 表示是 2 的幂; SDL_MostSignificantBitIndex32 基于 CPU 专用指令实现,返回最高置 1 位的索引(0~31),0 值返回 -1; SDL 位操作函数性能远超手动实现,适合高频调用的性能关键路径。
      • 2026年-3月-7日
      • 0 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_字节序(CategoryEndian) 2026-3-6
      SDL3_API分类参考_字节序(CategoryEndian) 字节序子系统(CategoryEndian) SDL 提供了用于转换特定字节序数值的函数,可实现不同字节序(大小端)之间的转换。 这些函数分为两类: 无条件字节序交换(SDL_Swap16、SDL_Swap32、SDL_Swap64、SDL_SwapFloat):无论当前系统字节序如何,始终反转数值的字节顺序; 与系统原生字节序互转(SDL_Swap16LE/SDL_Swap16BE、SDL_Swap32LE/SDL_Swap32BE、SDL_SwapFloatLE/SDL_SwapFloatBE):这类功能由宏实现,若无需交换则直接返回原值(无操作)——例如 x86(小端)处理器上,SDL_Swap32LE 无动作,SDL_Swap32BE 反转字节;PowerPC(大端)处理器上则行为相反。 字节序交换例程为内联函数,会尽可能使用编译器内联函数、内联汇编等优化手段,保证字节交换的执行效率。 函数 SDL_Swap16:无条件交换 16 位整数的字节序(返回交换后的值) SDL_Swap32:无条件交换 32 位整数的字节序(返回交换后的值) SDL_Swap64:无条件交换 64 位整数的字节序(返回交换后的值) SDL_SwapFloat:无条件交换 32 位浮点数的字节序(返回交换后的值) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_BIG_ENDIAN:宏常量,标识大端字节序(高位字节存储在低地址) SDL_BYTEORDER:编译期宏,标识当前系统的原生字节序(值为 SDL_BIG_ENDIAN 或 SDL_LIL_ENDIAN) SDL_FLOATWORDORDER:宏常量,标识浮点数的字节序(通常与整数字节序一致) SDL_LIL_ENDIAN:宏常量,标识小端字节序(低位字节存储在低地址,等价于 SDL_LITTLE_ENDIAN) SDL_Swap16BE:将 16 位整数从大端序转换为系统原生字节序(小端系统交换,大端系统无操作) SDL_Swap16LE:将 16 位整数从小端序转换为系统原生字节序(大端系统交换,小端系统无操作) SDL_Swap32BE:将 32 位整数从大端序转换为系统原生字节序(小端系统交换,大端系统无操作) SDL_Swap32LE:将 32 位整数从小端序转换为系统原生字节序(大端系统交换,小端系统无操作) SDL_Swap64BE:将 64 位整数从大端序转换为系统原生字节序(小端系统交换,大端系统无操作) SDL_Swap64LE:将 64 位整数从小端序转换为系统原生字节序(大端系统交换,小端系统无操作) SDL_SwapFloatBE:将 32 位浮点数从大端序转换为系统原生字节序(小端系统交换,大端系统无操作) SDL_SwapFloatLE:将 32 位浮点数从小端序转换为系统原生字节序(大端系统交换,小端系统无操作) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_Swap16 CDecl (ByVal x As UShort) As UShort Declare Function SDL_Swap32 CDecl (ByVal x As UInteger) As UInteger Declare Function SDL_Swap64 CDecl (ByVal x As ULongInt) As ULongInt Declare Function SDL_SwapFloat CDecl (ByVal x As Single) As Single ' 补充字节序宏定义(若 FreeBASIC 绑定未包含) #If Not Defined(SDL_BIG_ENDIAN) #Define SDL_BIG_ENDIAN 4321 #EndIf #If Not Defined(SDL_LIL_ENDIAN) #Define SDL_LIL_ENDIAN 1234 #EndIf #If Not Defined(SDL_BYTEORDER) ' x86/x86_64 默认为小端,其他架构需根据实际情况调整 #Define SDL_BYTEORDER SDL_LIL_ENDIAN #EndIf ' 定义大小端转换宏(模拟 SDL 原生宏行为) #If SDL_BYTEORDER = SDL_LIL_ENDIAN #Define SDL_Swap16LE(x) (x) ' 小端系统:LE转原生=无操作 #Define SDL_Swap16BE(x) SDL_Swap16(x)' 小端系统:BE转原生=交换 #Define SDL_Swap32LE(x) (x) ' 小端系统:LE转原生=无操作 #Define SDL_Swap32BE(x) SDL_Swap32(x)' 小端系统:BE转原生=交换 #Define SDL_SwapFloatLE(x) (x) ' 小端系统:LE转原生=无操作 #Define SDL_SwapFloatBE(x) SDL_SwapFloat(x)' 小端系统:BE转原生=交换 #Else #Define SDL_Swap16LE(x) SDL_Swap16(x)' 大端系统:LE转原生=交换 #Define SDL_Swap16BE(x) (x) ' 大端系统:BE转原生=无操作 #Define SDL_Swap32LE(x) SDL_Swap32(x)' 大端系统:LE转原生=交换 #Define SDL_Swap32BE(x) (x) ' 大端系统:BE转原生=无操作 #Define SDL_SwapFloatLE(x) SDL_SwapFloat(x)' 大端系统:LE转原生=交换 #Define SDL_SwapFloatBE(x) (x) ' 大端系统:BE转原生=无操作 #EndIf ' 打印字节序信息 Sub PrintEndianInfo() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【系统字节序信息】") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "原生字节序:%s", _ IIf(SDL_BYTEORDER = SDL_LIL_ENDIAN, "小端 (LIL_ENDIAN)", "大端 (BIG_ENDIAN)")) ' 示例:32位整数 0x12345678 的字节序 Dim As UInteger test32 = &H12345678 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "原始32位值:0x%08X", test32) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "无条件交换后:0x%08X", SDL_Swap32(test32)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "BE转原生后:0x%08X", SDL_Swap32BE(test32)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "LE转原生后:0x%08X", SDL_Swap32LE(test32)) End Sub ' 模拟文件/网络数据读写(大端序) Sub HandleBigEndianData() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【处理大端序数据】") ' 假设从文件/网络读取的大端序数据 Dim As UShort be16 = &H1234 ' 大端序 16 位数据 Dim As UInteger be32 = &H12345678 ' 大端序 32 位数据 Dim As Single beFloat = 123.456 ' 大端序浮点数 ' 转换为系统原生字节序 Dim As UShort native16 = SDL_Swap16BE(be16) Dim As UInteger native32 = SDL_Swap32BE(be32) Dim As Single nativeFloat = SDL_SwapFloatBE(beFloat) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "大端序16位:0x%04X → 原生序:0x%04X", be16, native16) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "大端序32位:0x%08X → 原生序:0x%08X", be32, native32) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "大端序浮点数:%.3f → 原生序:%.3f", beFloat, nativeFloat) ' 将原生序数据转换回大端序(用于写入文件/网络) Dim As UShort be16_again = SDL_Swap16BE(native16) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "原生序转回大端序:0x%04X", be16_again) End Sub ' 字节序转换性能示例 Sub PerformanceTest() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【字节序转换性能测试】") Const TEST_COUNT As ULongInt = 100000000 ' 1亿次转换 Dim As UInteger value = &H11223344 Dim As UInteger result Dim As ULongInt startTicks, endTicks ' 测试无条件交换 startTicks = SDL_GetPerformanceCounter() For i As ULongInt = 1 To TEST_COUNT result = SDL_Swap32(value) Next endTicks = SDL_GetPerformanceCounter() Dim As Double elapsed = (endTicks - startTicks) / SDL_GetPerformanceFrequency() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_Swap32 执行%llu次耗时:%.3f秒 (单次:%.6f微秒)", _ TEST_COUNT, elapsed, elapsed * 1000000 / TEST_COUNT) ' 测试条件交换(LE转原生,小端系统无操作) startTicks = SDL_GetPerformanceCounter() For i As ULongInt = 1 To TEST_COUNT result = SDL_Swap32LE(value) Next endTicks = SDL_GetPerformanceCounter() elapsed = (endTicks - startTicks) / SDL_GetPerformanceFrequency() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_Swap32LE 执行%llu次耗时:%.3f秒 (单次:%.6f微秒)", _ TEST_COUNT, elapsed, elapsed * 1000000 / TEST_COUNT) 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 ' 运行示例 PrintEndianInfo() HandleBigEndianData() PerformanceTest() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 字节序基础概念: 小端(LIL_ENDIAN):低位字节存低地址,高位字节存高地址(x86/x86_64、ARM 主流模式); 大端(BIG_ENDIAN):高位字节存低地址,低位字节存高地址(网络协议、部分嵌入式CPU); 示例:数值 0x12345678 在小端系统中存储为 0x78 0x56 0x34 0x12,大端系统中存储为 0x12 0x34 0x56 0x78。 SDL 字节序函数/宏的使用场景: 函数/宏 适用场景 SDL_SwapXXX 需强制反转字节序(如手动处理数据) SDL_SwapXXXBE 读取大端序数据(文件/网络)转原生序 SDL_SwapXXXLE 读取小端序数据转原生序 SDL_BYTEORDER 编译期判断系统原生字节序 性能优化要点: SDL 的字节序交换函数为内联实现,无函数调用开销; SDL_SwapXXXLE/BE 宏在无需交换时为「空操作」,性能接近直接赋值; 编译器会对频繁调用的字节交换操作做进一步优化(如内联汇编、SIMD)。 跨平台数据交互规范: 网络协议、二进制文件通常使用大端序(网络字节序); 读取外部数据时,先用 SDL_SwapXXXBE 转换为系统原生序,处理完成后再用 SDL_SwapXXXBE 转回大端序写入; 避免直接操作字节数组,优先使用 SDL 提供的转换函数,减少出错概率。 总结 核心优势: 统一的跨平台字节序转换接口,无需手动编写字节交换逻辑; 条件转换宏(LE/BE)自动适配系统字节序,无多余开销; 内联实现+编译器优化,保证字节交换的极致性能; 覆盖整数(16/32/64位)和浮点数,满足各类数据转换需求。 使用建议: 处理外部数据(文件/网络)时,优先使用 SDL_SwapXXXBE/LE 转换为系统原生序; 仅需强制反转字节序时,使用 SDL_SwapXXX; 编译期判断字节序用 SDL_BYTEORDER,运行时无需判断(转换宏已自动处理); 批量数据转换时,结合 SIMD 进一步提升性能(如 SDL_SIMD 相关接口)。 关键点回顾: SDL_SwapXXXBE/LE 是处理跨平台数据的核心,自动适配系统字节序; SDL 字节序函数为内联实现,性能接近手写汇编; 网络/二进制文件数据优先使用大端序,通过 SDL_SwapXXXBE 转换后再处理。
      • 2026年-3月-6日
      • 9 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_编译器内联函数(CategoryIntrinsics) 2026-3-6
      SDL3_API分类参考_编译器内联函数(CategoryIntrinsics) 编译器内联函数子系统(CategoryIntrinsics) SDL 会通过预处理指令的灵活处理,判断编译器是否支持特定 CPU 架构的内联函数(intrinsics)——这一判断过程并不简单,往往依赖于系统特性、编译工具版本及其他外部因素。 包含 SDL 头文件的应用程序,可通过统一的预处理宏定义判断是否能安全使用特定 CPU 架构的编译器内联函数。注意:这些宏仅表示编译器具备使用对应内联函数的能力;运行时仍需通过 CPU 信息函数(如 SDL_HasSSE()、SDL_HasNEON())检查当前系统是否支持该指令集,否则程序可能因执行不支持的 CPU 指令而崩溃。 SDL 仅在编译器支持对应内联函数时才定义相关预处理宏,因此应用程序应使用 #ifdef(而非 #if)进行检查。 此外,SDL 会自动包含指令集对应的系统头文件:例如若 SDL 定义了 SDL_SSE2_INTRINSICS,则会自动 #include <emmintrin.h>。 函数 (无) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_ALTIVEC_INTRINSICS:编译期宏,定义则表示编译器支持 PowerPC 架构的 AltiVec 内联函数,且已包含对应头文件 SDL_AVX2_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 AVX2 内联函数,且已包含对应头文件 SDL_AVX512F_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 AVX-512F 内联函数,且已包含对应头文件 SDL_AVX_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 AVX 内联函数,且已包含对应头文件 SDL_HAS_TARGET_ATTRIBS:编译期宏,定义则表示编译器支持目标架构属性(如 GCC 的 attribute((target))) SDL_LASX_INTRINSICS:编译期宏,定义则表示编译器支持龙芯架构的 LASX 内联函数,且已包含对应头文件 SDL_LSX_INTRINSICS:编译期宏,定义则表示编译器支持龙芯架构的 LSX 内联函数,且已包含对应头文件 SDL_MMX_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 MMX 内联函数,且已包含对应头文件 SDL_NEON_INTRINSICS:编译期宏,定义则表示编译器支持 ARM 架构的 NEON 内联函数,且已包含对应头文件 SDL_SSE2_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 SSE2 内联函数,且已包含对应头文件(emmintrin.h) SDL_SSE3_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 SSE3 内联函数,且已包含对应头文件(pmmintrin.h) SDL_SSE4_1_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 SSE4.1 内联函数,且已包含对应头文件(smmintrin.h) SDL_SSE4_2_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 SSE4.2 内联函数,且已包含对应头文件(nmmintrin.h) SDL_SSE_INTRINSICS:编译期宏,定义则表示编译器支持 x86 架构的 SSE 内联函数,且已包含对应头文件(xmmintrin.h) SDL_TARGETING:编译期宏,用于标记当前编译目标架构的内联函数支持状态 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充 CPU 信息函数声明(用于运行时检测) Declare Function SDL_HasSSE2 CDecl () As Integer Declare Function SDL_HasAVX2 CDecl () As Integer Declare Function SDL_HasNEON CDecl () As Integer ' 编译期:判断编译器是否支持特定内联函数 #If Defined(SDL_SSE2_INTRINSICS) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器支持 SSE2 内联函数") ' SDL 已自动包含 emmintrin.h,可直接使用 SSE2 内联函数 #Define SUPPORT_SSE2_COMPILE 1 #Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器不支持 SSE2 内联函数") #Define SUPPORT_SSE2_COMPILE 0 #EndIf #If Defined(SDL_AVX2_INTRINSICS) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器支持 AVX2 内联函数") #Define SUPPORT_AVX2_COMPILE 1 #Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器不支持 AVX2 内联函数") #Define SUPPORT_AVX2_COMPILE 0 #EndIf #If Defined(SDL_NEON_INTRINSICS) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器支持 NEON 内联函数") #Define SUPPORT_NEON_COMPILE 1 #Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【编译期】编译器不支持 NEON 内联函数") #Define SUPPORT_NEON_COMPILE 0 #EndIf ' SIMD 数据加法示例(SSE2 实现) Sub SIMDAdd_SSE2(ByVal a As Single Ptr, ByVal b As Single Ptr, ByVal c As Single Ptr, ByVal count As Integer) ' 仅当编译期支持 SSE2 且运行期 CPU 支持时执行 If (SUPPORT_SSE2_COMPILE = 0 Or SDL_HasSSE2() = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "无法执行 SSE2 优化:编译/运行期不支持") Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "使用 SSE2 内联函数执行 SIMD 加法") ' 注意:FreeBASIC 对 x86 内联函数的支持需结合编译器特性,此处为逻辑示例 Dim As Integer i = 0 ' SSE2 每次处理 4 个单精度浮点数(128 位) While (i + 3 < count) ' 示例:使用 _mm_load_ps/_mm_add_ps/_mm_store_ps 等 SSE2 内联函数 ' __m128 vecA = _mm_load_ps(a + i); ' __m128 vecB = _mm_load_ps(b + i); ' __m128 vecC = _mm_add_ps(vecA, vecB); ' _mm_store_ps(c + i, vecC); ' 模拟 SSE2 并行加法(实际需替换为真实内联函数) c[i] = a[i] + b[i] c[i+1] = a[i+1] + b[i+1] c[i+2] = a[i+2] + b[i+2] c[i+3] = a[i+3] + b[i+3] i += 4 Wend ' 处理剩余数据 While (i < count) c[i] = a[i] + b[i] i += 1 Wend End Sub ' 通用数据加法(无 SIMD 优化) Sub SIMDAdd_Generic(ByVal a As Single Ptr, ByVal b As Single Ptr, ByVal c As Single Ptr, ByVal count As Integer) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "使用通用指令执行加法") For i As Integer = 0 To count - 1 c[i] = a[i] + b[i] Next 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 ' 运行期:检测 CPU 是否支持对应指令集 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【运行期】CPU 指令集支持情况") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE2 支持:%s", IIf(SDL_HasSSE2(), "是", "否")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AVX2 支持:%s", IIf(SDL_HasAVX2(), "是", "否")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NEON 支持:%s", IIf(SDL_HasNEON(), "是", "否")) ' 测试数据 Const DATA_COUNT As Integer = 100 Dim As Single a(DATA_COUNT-1), b(DATA_COUNT-1), c(DATA_COUNT-1) For i As Integer = 0 To DATA_COUNT-1 a[i] = i * 1.0 b[i] = i * 2.0 Next ' 优先使用 SSE2 优化,否则使用通用实现 If (SUPPORT_SSE2_COMPILE = 1 And SDL_HasSSE2() = 1) Then SIMDAdd_SSE2(@a[0], @b[0], @c[0], DATA_COUNT) Else SIMDAdd_Generic(@a[0], @b[0], @c[0], DATA_COUNT) End If ' 打印结果(前 5 个) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "加法结果(前5个):") For i As Integer = 0 To 4 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "c[%d] = %.1f + %.1f = %.1f", i, a[i], b[i], c[i]) Next ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 编译期 vs 运行期检测的区别: 编译期宏(SDL_XXX_INTRINSICS):仅判断「编译器是否能识别对应内联函数」,不代表运行时 CPU 支持; 运行期函数(SDL_HasXXX()):判断「当前运行的 CPU 是否支持该指令集」,是执行内联函数的最终依据; 必须同时满足「编译期支持 + 运行期支持」,才能安全使用内联函数。 头文件自动包含规则: SDL 会根据宏定义自动包含对应指令集的系统头文件,无需手动 #include: 宏 自动包含的头文件 SDL_SSE_INTRINSICS xmmintrin.h SDL_SSE2_INTRINSICS emmintrin.h SDL_AVX2_INTRINSICS avx2intrin.h SDL_NEON_INTRINSICS arm_neon.h 宏检查的正确方式: 必须使用 #ifdef SDL_XXX_INTRINSICS(而非 #if SDL_XXX_INTRINSICS); SDL 仅在支持时定义宏,不支持时宏不存在——#if 会因宏未定义导致编译错误,#ifdef 则安全。 目标架构属性(SDL_HAS_TARGET_ATTRIBS): 定义该宏时,编译器支持「按函数粒度指定目标架构」(如 GCC 的 __attribute__((target("sse4.2")))); 可用于为不同函数编译不同指令集版本,运行时动态选择。 总结 核心优势: 统一的编译期宏定义,避免开发者手动适配不同编译器/平台的内联函数头文件和检测逻辑; 自动包含指令集头文件,减少手动引入错误; 与 SDL CPUInfo 子系统配合,实现「编译期验证 + 运行期检测」的双层安全校验; 覆盖主流架构的内联函数(x86/ARM/龙芯/PowerPC),满足多平台优化需求。 使用建议: 编译期用 #ifdef SDL_XXX_INTRINSICS 判断编译器是否支持内联函数,隔离优化代码; 运行期用 SDL_HasXXX() 检测 CPU 支持,决定是否执行优化逻辑; 始终提供通用实现作为降级方案,避免无指令集支持时程序崩溃; 对性能关键路径(如图形渲染、数据处理)使用内联函数优化,非关键路径使用通用实现。 关键点回顾: SDL_XXX_INTRINSICS 宏仅表示编译器支持内联函数,运行时仍需 CPUInfo 检测; 宏检查必须用 #ifdef,避免未定义宏导致的编译错误; SDL 自动包含指令集头文件,无需手动引入; 优化代码需提供降级方案,保证程序兼容性。
      • 2026年-3月-6日
      • 11 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_CPU信息(CategoryCPUInfo) 2026-3-6
      SDL3_API分类参考_CPU信息(CategoryCPUInfo) CPU信息子系统(CategoryCPUInfo) SDL 提供了一套 CPU 特性检测接口,主要用于判断系统是否支持各类 SIMD(单指令多数据)指令集,同时也能获取系统内存大小、逻辑 CPU 核心数等关键硬件信息。 CPU 指令集检测函数(如 SDL_HasSSE()、SDL_HasNEON())在所有平台上均可用——即使某些指令集对当前架构无意义(例如 ARM 处理器永远不支持 SSE,x86 处理器永远不支持 NEON),这些函数仍会存在,只是返回 false。 函数 SDL_GetCPUCacheLineSize:获取 CPU 缓存行大小(字节),优化内存访问对齐时使用 SDL_GetNumLogicalCPUCores:获取系统逻辑 CPU 核心数(超线程会被计入,如 8 核 16 线程返回 16) SDL_GetSIMDAlignment:获取 SIMD 指令集要求的内存对齐大小(字节),分配 SIMD 数据缓冲区时需满足该对齐 SDL_GetSystemPageSize:获取系统内存页大小(字节),内存分配/映射时的基础单位 SDL_GetSystemRAM:获取系统总物理内存大小(MB),用于判断硬件性能等级 SDL_HasAltiVec:检测 CPU 是否支持 PowerPC 架构的 AltiVec 指令集(返回非 0 表示支持) SDL_HasARMSIMD:检测 CPU 是否支持 ARM 架构的基础 SIMD 指令集(返回非 0 表示支持) SDL_HasAVX:检测 CPU 是否支持 x86 架构的 AVX 指令集(返回非 0 表示支持) SDL_HasAVX2:检测 CPU 是否支持 x86 架构的 AVX2 指令集(返回非 0 表示支持) SDL_HasAVX512F:检测 CPU 是否支持 x86 架构的 AVX-512F 基础指令集(返回非 0 表示支持) SDL_HasLASX:检测 CPU 是否支持龙芯架构的 LASX 指令集(返回非 0 表示支持) SDL_HasLSX:检测 CPU 是否支持龙芯架构的 LSX 指令集(返回非 0 表示支持) SDL_HasMMX:检测 CPU 是否支持 x86 架构的 MMX 指令集(返回非 0 表示支持) SDL_HasNEON:检测 CPU 是否支持 ARM 架构的 NEON 高级 SIMD 指令集(返回非 0 表示支持) SDL_HasSSE:检测 CPU 是否支持 x86 架构的 SSE 指令集(返回非 0 表示支持) SDL_HasSSE2:检测 CPU 是否支持 x86 架构的 SSE2 指令集(返回非 0 表示支持) SDL_HasSSE3:检测 CPU 是否支持 x86 架构的 SSE3 指令集(返回非 0 表示支持) SDL_HasSSE41:检测 CPU 是否支持 x86 架构的 SSE4.1 指令集(返回非 0 表示支持) SDL_HasSSE42:检测 CPU 是否支持 x86 架构的 SSE4.2 指令集(返回非 0 表示支持) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_CACHELINE_SIZE:编译期宏,定义默认的 CPU 缓存行大小(通常为 64 字节,实际硬件可能不同,建议运行时用 SDL_GetCPUCacheLineSize 获取) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_GetCPUCacheLineSize CDecl () As Integer Declare Function SDL_GetNumLogicalCPUCores CDecl () As Integer Declare Function SDL_GetSIMDAlignment CDecl () As Integer Declare Function SDL_GetSystemPageSize CDecl () As Integer Declare Function SDL_GetSystemRAM CDecl () As Integer Declare Function SDL_HasAltiVec CDecl () As Integer Declare Function SDL_HasARMSIMD CDecl () As Integer Declare Function SDL_HasAVX CDecl () As Integer Declare Function SDL_HasAVX2 CDecl () As Integer Declare Function SDL_HasAVX512F CDecl () As Integer Declare Function SDL_HasLASX CDecl () As Integer Declare Function SDL_HasLSX CDecl () As Integer Declare Function SDL_HasMMX CDecl () As Integer Declare Function SDL_HasNEON CDecl () As Integer Declare Function SDL_HasSSE CDecl () As Integer Declare Function SDL_HasSSE2 CDecl () As Integer Declare Function SDL_HasSSE3 CDecl () As Integer Declare Function SDL_HasSSE41 CDecl () As Integer Declare Function SDL_HasSSE42 CDecl () As Integer ' 打印SIMD指令集支持情况 Sub PrintSIMDSupport() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【SIMD 指令集支持情况】") ' x86 架构指令集 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "MMX: %s", IIf(SDL_HasMMX(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE: %s", IIf(SDL_HasSSE(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE2: %s", IIf(SDL_HasSSE2(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE3: %s", IIf(SDL_HasSSE3(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE4.1: %s", IIf(SDL_HasSSE41(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SSE4.2: %s", IIf(SDL_HasSSE42(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AVX: %s", IIf(SDL_HasAVX(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AVX2: %s", IIf(SDL_HasAVX2(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AVX512F:%s", IIf(SDL_HasAVX512F(), "支持", "不支持")) ' ARM 架构指令集 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "ARM SIMD: %s", IIf(SDL_HasARMSIMD(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NEON: %s", IIf(SDL_HasNEON(), "支持", "不支持")) ' 其他架构指令集 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AltiVec: %s", IIf(SDL_HasAltiVec(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "LSX: %s", IIf(SDL_HasLSX(), "支持", "不支持")) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "LASX: %s", IIf(SDL_HasLASX(), "支持", "不支持")) End Sub ' 打印系统/CPU硬件信息 Sub PrintSystemInfo() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【系统/CPU 硬件信息】") ' CPU 核心数 Dim As Integer coreCount = SDL_GetNumLogicalCPUCores() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "逻辑CPU核心数:%d", coreCount) ' 系统内存 Dim As Integer ramSize = SDL_GetSystemRAM() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "总物理内存:%d MB (%.2f GB)", ramSize, ramSize / 1024.0) ' 缓存行大小 Dim As Integer cacheLineSize = SDL_GetCPUCacheLineSize() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "CPU缓存行大小:%d 字节 (编译期默认:%d 字节)", cacheLineSize, SDL_CACHELINE_SIZE) ' SIMD对齐要求 Dim As Integer simdAlign = SDL_GetSIMDAlignment() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SIMD内存对齐要求:%d 字节", simdAlign) ' 系统页大小 Dim As Integer pageSize = SDL_GetSystemPageSize() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统内存页大小:%d 字节", pageSize) End Sub ' 根据硬件特性调整程序配置 Sub AdjustAppConfig() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据硬件特性调整配置】") ' 根据内存大小设置纹理质量 Dim As Integer ramSize = SDL_GetSystemRAM() If (ramSize >= 16384) Then ' 16GB 及以上 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内存充足,启用4K纹理质量") ElseIf (ramSize >= 8192) Then ' 8GB 及以上 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内存中等,启用2K纹理质量") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内存较少,启用1080P纹理质量") End If ' 根据CPU核心数设置线程池大小 Dim As Integer coreCount = SDL_GetNumLogicalCPUCores() Dim As Integer threadCount = IIf(coreCount > 4, coreCount - 1, coreCount) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设置线程池大小:%d 线程", threadCount) ' 根据SIMD指令集启用优化 If (SDL_HasAVX2() Or SDL_HasNEON()) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "启用高级SIMD优化(图形渲染/数据处理)") ElseIf (SDL_HasSSE42()) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "启用基础SIMD优化(数据处理)") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "使用通用CPU指令集(无SIMD优化)") 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 ' 打印硬件信息 PrintSystemInfo() PrintSIMDSupport() ' 根据硬件调整配置 AdjustAppConfig() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 SIMD 指令集检测规则: 所有指令集检测函数返回 非 0 表示支持,0 表示不支持; 跨架构检测时(如 x86 上检测 NEON),函数仍会返回 0,不会报错; 建议运行时动态检测,而非编译期判断——同一编译产物可能运行在不同指令集的 CPU 上。 内存对齐关键要点: SDL_GetSIMDAlignment() 返回的是当前 CPU SIMD 指令集要求的最小对齐大小(如 AVX2 要求 32 字节,NEON 要求 16 字节); 分配 SIMD 数据缓冲区时,需满足该对齐要求,否则可能导致程序崩溃或性能下降; SDL 提供 SDL_aligned_alloc/SDL_aligned_free 函数,可便捷分配对齐内存。 硬件信息的应用场景: 函数 典型应用场景 SDL_GetNumLogicalCPUCores 设置线程池大小、任务并行数 SDL_GetSystemRAM 调整内存占用、纹理/贴图质量等级 SDL_GetCPUCacheLineSize 优化内存访问模式(避免缓存行颠簸) SDL_GetSystemPageSize 内存映射(mmap)、大内存块分配 SDL_CACHELINE_SIZE 宏说明: 编译期默认值通常为 64 字节(主流 CPU 的缓存行大小); 实际硬件的缓存行大小可能不同(如部分嵌入式 CPU 为 32 字节),建议运行时用 SDL_GetCPUCacheLineSize 获取真实值。 总结 核心优势: 统一的跨平台硬件检测接口,无需适配不同架构的原生检测方法; 完整覆盖主流 SIMD 指令集(x86/ARM/龙芯/PowerPC),满足多架构优化需求; 硬件信息获取函数返回值直观,无需解析复杂的系统信息结构体; 所有函数均为纯查询操作,无副作用,调用成本极低。 使用建议: 游戏/高性能应用中,根据 SIMD 指令集动态启用优化代码路径(如 AVX2 优化的图形渲染、NEON 优化的音频处理); 根据 CPU 核心数动态调整线程池大小,避免过度并行导致的线程竞争; 根据系统内存大小分级调整资源加载策略(如大内存加载高清纹理,小内存加载压缩纹理); 分配 SIMD 数据缓冲区时,务必遵循 SDL_GetSIMDAlignment() 返回的对齐要求。 关键点回顾: SIMD 指令集检测函数跨平台可用,非目标架构返回 false,无需额外判空; SDL_GetSIMDAlignment() 是 SIMD 内存分配的关键,需满足对齐要求; 硬件信息可用于动态调整程序配置,实现「低配能跑、高配优化」的自适应效果。
      • 2026年-3月-6日
      • 7 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_平台(CategoryPlatform) 2026-3-6
      SDL3_API分类参考_平台(CategoryPlatform) 平台子系统(CategoryPlatform) SDL 提供了在编译期和运行期识别应用程序运行平台的方法,帮助开发者实现跨平台的差异化逻辑处理。 函数 SDL_GetPlatform:运行时获取当前平台名称(返回字符串指针,如 "Windows"、"Linux"、"macOS" 等,无需手动释放) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_PLATFORM_3DS:编译期宏,标识任天堂 3DS 平台 SDL_PLATFORM_AIX:编译期宏,标识 IBM AIX 系统 SDL_PLATFORM_ANDROID:编译期宏,标识 Android 平台 SDL_PLATFORM_APPLE:编译期宏,标识苹果系平台(包含 macOS/iOS/tvOS 等) SDL_PLATFORM_BSDI:编译期宏,标识 BSDI 系统 SDL_PLATFORM_CYGWIN:编译期宏,标识 Cygwin 环境(Windows 下的类 Unix 层) SDL_PLATFORM_EMSCRIPTEN:编译期宏,标识 Emscripten 编译的 WASM/HTML5 平台 SDL_PLATFORM_FREEBSD:编译期宏,标识 FreeBSD 系统 SDL_PLATFORM_GDK:编译期宏,标识 Xbox GDK 开发套件平台 SDL_PLATFORM_HAIKU:编译期宏,标识 Haiku 操作系统 SDL_PLATFORM_HPUX:编译期宏,标识 HP-UX 系统 SDL_PLATFORM_HURD:编译期宏,标识 GNU Hurd 系统 SDL_PLATFORM_IOS:编译期宏,标识 iOS 平台 SDL_PLATFORM_IRIX:编译期宏,标识 SGI IRIX 系统 SDL_PLATFORM_LINUX:编译期宏,标识 Linux 系统 SDL_PLATFORM_MACOS:编译期宏,标识 macOS 系统 SDL_PLATFORM_NETBSD:编译期宏,标识 NetBSD 系统 SDL_PLATFORM_NGAGE:编译期宏,标识诺基亚 N-Gage 平台 SDL_PLATFORM_OPENBSD:编译期宏,标识 OpenBSD 系统 SDL_PLATFORM_OS2:编译期宏,标识 OS/2 系统 SDL_PLATFORM_OSF:编译期宏,标识 OSF/1 系统 SDL_PLATFORM_PS2:编译期宏,标识索尼 PS2 平台 SDL_PLATFORM_PSP:编译期宏,标识索尼 PSP 平台 SDL_PLATFORM_QNXNTO:编译期宏,标识 QNX Neutrino 系统 SDL_PLATFORM_RISCOS:编译期宏,标识 RISC OS 系统 SDL_PLATFORM_SOLARIS:编译期宏,标识 Solaris 系统 SDL_PLATFORM_TVOS:编译期宏,标识 tvOS 平台(苹果电视) SDL_PLATFORM_UNIX:编译期宏,标识通用 Unix 类系统 SDL_PLATFORM_VISIONOS:编译期宏,标识 visionOS 平台(苹果 Vision Pro) SDL_PLATFORM_VITA:编译期宏,标识索尼 PS Vita 平台 SDL_PLATFORM_WIN32:编译期宏,标识 32/64 位 Windows 平台(兼容 Win32/Win64) SDL_PLATFORM_WINDOWS:编译期宏,标识 Windows 平台(与 SDL_PLATFORM_WIN32 等价) SDL_PLATFORM_WINGDK:编译期宏,标识 Windows GDK 平台 SDL_PLATFORM_XBOXONE:编译期宏,标识 Xbox One 平台 SDL_PLATFORM_XBOXSERIES:编译期宏,标识 Xbox Series X/S 平台 SDL_WINAPI_FAMILY_PHONE:编译期宏,标识 Windows Phone 平台 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_GetPlatform CDecl () As ZString Ptr ' 编译期平台判断示例(预处理指令) #If Defined(SDL_PLATFORM_WINDOWS) #Define PLATFORM_NAME "Windows" #Elif Defined(SDL_PLATFORM_LINUX) #Define PLATFORM_NAME "Linux" #Elif Defined(SDL_PLATFORM_MACOS) #Define PLATFORM_NAME "macOS" #Elif Defined(SDL_PLATFORM_ANDROID) #Define PLATFORM_NAME "Android" #Elif Defined(SDL_PLATFORM_IOS) #Define PLATFORM_NAME "iOS" #Elif Defined(SDL_PLATFORM_EMSCRIPTEN) #Define PLATFORM_NAME "Emscripten (WASM/HTML5)" #Else #Define PLATFORM_NAME "Unknown Platform" #EndIf ' 运行期平台处理逻辑 Sub HandlePlatformSpecificLogic() Dim As ZString Ptr runtimePlatform = SDL_GetPlatform() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "运行期检测到平台:%s", *runtimePlatform) ' 根据运行期平台执行差异化逻辑 Select Case *runtimePlatform Case "Windows" SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "执行 Windows 专属逻辑:适配注册表、路径分隔符为 \") ' 示例:Windows 下的文件路径处理、注册表访问等 Case "Linux" SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "执行 Linux 专属逻辑:适配 /home 目录、权限管理") ' 示例:Linux 下的系统配置文件读取、权限检查等 Case "Mac OS X", "macOS" SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "执行 macOS 专属逻辑:适配 ~/Library 目录、沙盒权限") ' 示例:macOS 下的应用沙盒、Finder 集成等 Case "Android" SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "执行 Android 专属逻辑:适配 APK 资源、JNI 调用") ' 示例:Android 下的权限申请、JNI 交互等 Case "iOS" SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "执行 iOS 专属逻辑:适配沙盒、应用内购买") ' 示例:iOS 下的沙盒文件访问、IAP 处理等 Case Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未适配的平台:%s,使用通用逻辑", *runtimePlatform) End Select 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 ' 打印编译期平台信息 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "编译期检测到平台:%s", PLATFORM_NAME) ' 执行运行期平台逻辑 HandlePlatformSpecificLogic() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 编译期 vs 运行期平台检测: *编译期宏(SDLPLATFORM)**:在代码编译时确定平台,用于条件编译(如不同平台的代码分支、头文件引入); 运行期函数(SDL_GetPlatform):程序运行时获取实际平台名称,适用于「同一编译产物运行在多平台」的场景(如跨平台打包的应用、Emscripten 编译的 WASM)。 SDL_GetPlatform 返回值规范: 平台 返回字符串 Windows(32/64位) "Windows" Linux "Linux" macOS "Mac OS X" / "macOS" Android "Android" iOS "iOS" Emscripten "Emscripten" FreeBSD "FreeBSD" Xbox "Xbox One" / "Xbox Series X/S" 跨平台开发最佳实践: 编译期宏用于「不可变的平台差异」(如头文件、API 声明); 运行期检测用于「可变的运行环境」(如同一二进制包运行在不同 Linux 发行版); 优先使用 SDL 提供的跨平台 API 封装,减少直接的平台判断; 平台判断逻辑集中管理,避免散落在代码各处。 总结 核心优势: 同时支持编译期和运行期平台检测,覆盖不同跨平台开发场景; 统一的平台标识体系,避免开发者记忆不同平台的原生宏定义; SDL_GetPlatform 返回的字符串格式稳定,便于运行期逻辑判断; 编译期宏覆盖主流平台(PC、移动端、游戏主机、嵌入式),满足多平台开发需求。 使用建议: 编译期:用 #If Defined(SDL_PLATFORM_XXX) 做条件编译,隔离平台专属代码; 运行期:用 SDL_GetPlatform() 获取平台名称,执行差异化的运行逻辑; 避免过度依赖平台判断,优先使用 SDL 封装的跨平台接口(如文件路径、输入输出); 对 SDL 未覆盖的小众平台,可结合原生宏(如 __linux__、_WIN32)补充判断。 关键点回顾: SDL_GetPlatform() 是运行期平台检测的核心函数,返回值无需手动释放; 编译期宏(SDLPLATFORM*)用于条件编译,区分不同平台的编译逻辑; 跨平台开发应优先使用 SDL 封装的 API,仅在必要时做平台差异化处理。
      • 2026年-3月-6日
      • 8 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • 1
    • 2
    • 3
    • 4
    博主栏壁纸
    博主头像 勇芳

    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