You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rust中转换*const __CFData为String并获取键盘语言的问题

解决Rust中获取当前键盘语言并判断的问题

错误原因

你遇到的问题核心是对kTISPropertyLocalizedName的返回值类型判断错误:这个属性返回的是CFStringRef(和NSString是toll-free桥接的),而非你声明的*const __CFData。强行用CFDataGetBytePtr处理CFString/NSString对象,必然触发unrecognized selector错误——因为NSString根本没有bytes方法(该方法属于CFData)。

正确实现代码

以下是修正后的Rust代码,包含正确的类型处理和Core Foundation内存管理:

use core_foundation::{
    string::CFString,
    base::{CFRelease, CFTypeRef},
};
use std::ffi::CStr;

// 假设你的ffi模块已正确声明以下函数/常量
// ffi::TISCopyCurrentKeyboardLayoutInputSource() -> CFTypeRef;
// ffi::TISGetInputSourceProperty(source: CFTypeRef, property: CFTypeRef) -> CFTypeRef;
// ffi::kTISPropertyLocalizedName: CFTypeRef;

fn is_current_keyboard_english() -> bool {
    // 获取当前键盘布局输入源,返回对象需手动释放
    let current_source = unsafe { ffi::TISCopyCurrentKeyboardLayoutInputSource() };
    if current_source.is_null() {
        return false;
    }

    // 获取本地化名称(CFString类型)
    let localized_name = unsafe {
        ffi::TISGetInputSourceProperty(current_source, ffi::kTISPropertyLocalizedName)
    };
    if localized_name.is_null() {
        unsafe { CFRelease(current_source) };
        return false;
    }

    // 将CFString转换为Rust String
    let lang_str = unsafe {
        // 优先尝试快速获取C字符串指针(适用于UTF-8兼容的字符串)
        match CFString::new(localized_name).c_string_ptr() {
            Some(ptr) => CStr::from_ptr(ptr).to_str().unwrap_or_default().to_string(),
            None => {
                // 快速获取失败时,用缓冲区复制处理特殊字符
                let mut buf = [0u8; 256];
                let success = CFString::new(localized_name).get_cstring(
                    &mut buf,
                    core_foundation::string::CFStringEncoding::UTF8
                );
                if success {
                    CStr::from_bytes_until_nul(&buf).unwrap_or_default().to_str().unwrap_or_default().to_string()
                } else {
                    String::new()
                }
            }
        }
    };

    // 释放Core Foundation对象,避免内存泄漏
    unsafe {
        CFRelease(localized_name);
        CFRelease(current_source);
    }

    lang_str.contains("English")
}

关键注意事项

  • 类型匹配:务必对照官方文档确认TISGetInputSourceProperty返回的属性类型,kTISPropertyLocalizedName明确为CFString类型。
  • 内存管理:所有以Copy/Create开头的Core Foundation函数返回的对象,必须用CFRelease手动释放。
  • 字符串转换:优先用CFString::c_string_ptr提升效率,失败时再用缓冲区复制的方式兼容特殊字符场景。

内容的提问来源于stack exchange,提问作者hyoyin_Kyuoma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:30:16