论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
搜索
登录
搜索
勇芳
累计撰写
333
篇文章
累计收到
0
条评论
首页
栏目
论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
自定义幻灯片
推荐
联系勇芳软件
最新文章
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日
713 阅读
0 评论
VisualFreeBasic编程文档
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日
652 阅读
0 评论
VisualFreeBasic编程文档
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日
465 阅读
0 评论
VisualFreeBasic编程文档
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日
239 阅读
0 评论
VisualFreeBasic编程文档
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日
255 阅读
0 评论
VisualFreeBasic编程文档
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日
200 阅读
0 评论
VisualFreeBasic编程文档
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日
232 阅读
0 评论
VisualFreeBasic编程文档
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日
227 阅读
0 评论
VisualFreeBasic编程文档
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日
229 阅读
0 评论
VisualFreeBasic编程文档
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日
209 阅读
0 评论
VisualFreeBasic编程文档
1
2
3
4