系统适配子系统(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 管理,无需手动释放,但不可修改。
- Android 10+ 需申请
-
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 线程优先级是该模块的高频使用场景;
- 沙箱模式检测可帮助应用适配不同平台的权限限制,避免运行时错误。
评论一下?