在Rust中将 *const __CFData转换为字符串

uyhoqukh  于 2023-03-02  发布在  其他
关注(0)|答案(1)|浏览(105)

我正在尝试将生 rust 的*const __CFData转换为String
我正在尝试获取键盘语言并检查它是否是特定语言。

let current_source = ffi::TISCopyCurrentKeyboardLayoutInputSource();
let current_language = ffi::TISGetInputSourceProperty(current_source, ffi::kTISPropertyLocalizedName);
let language = CFDataGetBytePtr(current_language);
CStr::from_ptr(language).to_str().unwrap().to_string().contains("English")

我收到此运行时错误--[__NSCFConstantString bytes]: unrecognized selector sent to instance 0x7ff85dfed1d8
TISGetInputSourceProperty返回一个*const __CFDataCFDataGetBytePtr应该返回一个*const u8,但是它在该函数上失败,并出现上述错误。
我如何得到的语言,并检查它是什么生 rust ?TIA.

cbjzeqam

cbjzeqam1#

所以我稍微研究了一下,并得出了以下结论,* 似乎 * 可以工作。注意,就我所知,这个API肯定是不赞成的。
(the以下需要libc作为依赖项)

use libc::{size_t, c_void, c_char};

// A lot of these types taken from https://github.com/servo/core-foundation-rs/blob/0876315e2e434c2b5e5f406e7d540360c24b8c2e/core-foundation-sys/src/base.rs#L24
pub type CFStringEncoding = u32;
pub type Boolean = u8;
pub type CFIndex = isize;
pub static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;

#[repr(C)]
pub struct __CFString(c_void);
pub type CFStringRef = *const __CFString;

#[link(name = "Carbon", kind = "framework")]
extern "C" {
    fn TISCopyCurrentKeyboardInputSource() -> *const c_void;
    fn TISGetInputSourceProperty(a: *const c_void, b: *const c_void) -> CFStringRef;
    static kTISPropertyLocalizedName: *const c_void;
}

#[link(name = "CoreFoundation", kind = "framework")]
extern {
    pub fn CFStringGetCString(theString: CFStringRef,
        buffer: *mut c_char,
        bufferSize: CFIndex,
        encoding: CFStringEncoding)
        -> Boolean;
}

fn main() {
    unsafe {
        let v = vec![0; 256];
        let s = std::ffi::CString::from_vec_unchecked(v);
        let ptr = s.into_raw();

        let source = TISCopyCurrentKeyboardInputSource();
        let y = TISGetInputSourceProperty(source, kTISPropertyLocalizedName);
        CFStringGetCString(y, ptr, 256, kCFStringEncodingUTF8);

        println!("{:?}", std::ffi::CString::from_raw(ptr));
        // Prints "ABC" on my machine
    }
}

注意CFStringGetCStringPtr对我不起作用,因为它返回了一个空指针。我猜这是因为(docs):
如果字符串的内部存储不允许有效地返回[指针],则[返回] NULL。

相关问题