Rust系统级核心功能库CoreFoundation-sys的使用,CoreFoundation-sys提供底层跨平台系统API绑定与基础框架交互

CoreFoundation Rust Bindings

CoreFoundation-sys 包提供了在 macOS 上对 CoreFoundation C 库的声明和链接。遵循 *-sys 包的约定,CoreFoundation-sys 包不定义对原生库的高级抽象。

状态

CoreFoundation-sys crate 还在开发中。它目前导出了 CoreFoundation 中最基本的类型(数组、字典、字符串等)和函数,并且只在 macOS 的 x86_64 架构上进行了测试。

使用方法

Cargo.toml 中添加 CoreFoundation-sys 作为依赖:

[dependencies]
CoreFoundation-sys = "0.1.4"

导入 CoreFoundation_sys crate 并使用 Apple 提供的原生 CoreFoundation 库中定义的函数:

extern crate CoreFoundation_sys as cf;

完整示例代码

下面是一个使用 CoreFoundation-sys 创建和操作 CFString 的完整示例:

extern crate CoreFoundation_sys as cf;

use std::os::raw::c_void;
use std::ptr;

fn main() {
    unsafe {
        // 创建一个 CFString
        let string = b"Hello, CoreFoundation!\0";
        let cf_string = cf::CFStringCreateWithBytes(
            ptr::null(),                     // allocator
            string.as_ptr(),                 // bytes
            string.len() as cf::CFIndex,     // length
            cf::kCFStringEncodingUTF8,       // encoding
            0                                // isExternalRepresentation
        );
        
        // 获取字符串长度
        let length = cf::CFStringGetLength(cf_string);
        println!("String length: {}", length);
        
        // 检查是否包含子串
        let substring = b"Core\0";
        let cf_substring = cf::CFStringCreateWithBytes(
            ptr::null(),
            substring.as_ptr(),
            substring.len() as cf::CFIndex,
            cf::kCFStringEncodingUTF8,
            0
        );
        
        let range = cf::CFStringFind(
            cf_string,
            cf_substring,
            cf::kCFCompareCaseInsensitive
        );
        
        println!(
            "Substring found at location: {}, length: {}", 
            range.location, 
            range.length
        );
        
        // 释放内存
        cf::CFRelease(cf_string as *const c_void);
        cf::CFRelease(cf_substring as *const c_void);
    }
}

完整示例demo

下面是一个使用 CoreFoundation-sys 创建 CFArray 并遍历元素的完整示例:

extern crate CoreFoundation_sys as cf;

use std::os::raw::c_void;
use std::ptr;

fn main() {
    unsafe {
        // 创建3个CFString对象
        let strings = [
            b"Apple\0",
            b"Banana\0",
            b"Orange\0"
        ];
        
        let cf_strings: Vec<*const c_void> = strings.iter().map(|s| {
            let cf_str = cf::CFStringCreateWithBytes(
                ptr::null(),
                s.as_ptr(),
                s.len() as cf::CFIndex,
                cf::kCFStringEncodingUTF8,
                0
            );
            cf_str as *const c_void
        }).collect();
        
        // 创建CFArray
        let cf_array = cf::CFArrayCreate(
            ptr::null(),
            cf_strings.as_ptr(),
            cf_strings.len() as cf::CFIndex,
            &cf::kCFTypeArrayCallBacks
        );
        
        // 获取数组长度
        let count = cf::CFArrayGetCount(cf_array);
        println!("Array contains {} items", count);
        
        // 遍历数组元素
        for i in 0..count {
            let item = cf::CFArrayGetValueAtIndex(cf_array, i);
            let string_ref = item as cf::CFStringRef;
            
            // 获取字符串长度
            let length = cf::CFStringGetLength(string_ref);
            
            // 分配缓冲区
            let mut buffer = vec![0u8; length * 4 + 1];
            
            // 转换为UTF-8字符串
            let success = cf::CFStringGetCString(
                string_ref,
                buffer.as_mut_ptr() as *mut i8,
                buffer.len() as cf::CFIndex,
                cf::kCFStringEncodingUTF8
            );
            
            if success != 0 {
                let c_str = std::ffi::CStr::from_ptr(buffer.as_ptr() as *const i8);
                println!("Item {}: {:?}", i, c_str.to_string_lossy());
            }
        }
        
        // 释放内存
        for cf_str in cf_strings {
            cf::CFRelease(cf_str);
        }
        cf::CFRelease(cf_array as *const c_void);
    }
}

贡献

你可能会发现 CoreFoundation-sys 缺少一些你需要的功能。如果是这样,请在 Github 上提交 issue 或者发送包含新增功能的 pull request。

如果你计划提交 pull request,请注意代码的结构。CoreFoundation 框架中的每个头文件都有一个对应的源文件。例如,src/string.rs 包含来自 CoreFoundation/CFString.h 的定义。每个文件中的定义顺序与匹配头文件中的顺序大致相同。然后每个文件在 crate 根目录重新导出,例如 pub use string::*

贡献者

  • dcuddeback
  • oopsies49
  • burtonageo

许可证

版权所有 © 2015 David Cuddeback

根据 MIT 许可证分发。


1 回复

Rust系统级核心功能库CoreFoundation-sys使用指南

概述

CoreFoundation-sys是Rust的一个系统级库,提供了与Apple Core Foundation框架的底层绑定。这个库主要用于需要与macOS、iOS等Apple平台底层系统API交互的场景。

主要功能

  • 提供Core Foundation框架的原始绑定
  • 跨平台系统API访问
  • 基础数据类型和集合类型的交互
  • 内存管理和对象生命周期控制

安装方法

在Cargo.toml中添加依赖:

[dependencies]
core-foundation-sys = "0.8"

基本使用方法

1. 字符串处理

use core_foundation_sys::string::*;

unsafe {
    // 创建CFString
    let hello = CFStringCreateWithCString(
        std::ptr::null(), 
        "Hello, World!\0".as_ptr() as *const i8, 
        kCFStringEncodingUTF8
    );
    
    // 获取字符串长度
    let length = CFStringGetLength(hello);
    println!("String length: {}", length);
    
    // 释放CFString
    CFRelease(hello as *const _);
}

2. 数组处理

use core_foundation_sys::array::*;
use core_foundation_sys::base::*;

unsafe {
    // 创建CFArray
    let values = [1 as *const _, 2 as *const _, 3 as *const _];
    let array = CFArrayCreate(
        std::ptr::null(), 
        values.as_ptr(), 
        values.len() as CFIndex, 
        &kCFTypeArrayCallBacks
    );
    
    // 获取数组元素数量
    let count = CFArrayGetCount(array);
    println!("Array count: {}", count);
    
    // 释放CFArray
    CFRelease(array as *const _);
}

3. 字典处理

use core_foundation_sys::dictionary::*;
use core_foundation_sys::string::*;
use core_foundation_sys::number::*;
use core_foundation_sys::base::*;

unsafe {
    // 创建键和值
    let keys = [CFStringCreateWithCString(
        std::ptr::null(), 
        "name\0".as_ptr() as *const i8, 
        kCFStringEncodingUTF8
    )];
    
    let values = [CFNumberCreate(
        std::ptr::null(), 
        kCFNumberSInt32Type, 
        &42 as *const _ as *const _
    )];
    
    // 创建CFDictionary
    let dict = CFDictionaryCreate(
        std::ptr::null(), 
        keys.as_ptr() as *const _, 
        values.as_ptr() as *const _, 
        1, 
        &kCFTypeDictionaryKeyCallBacks, 
        &kCFTypeDictionaryValueCallBacks
    );
    
    // 释放资源
    CFRelease(keys[0] as *const _);
    CFRelease(values[0] as *const _);
    CFRelease(dict as *const _);
}

内存管理注意事项

CoreFoundation-sys使用手动内存管理,需要遵循Core Foundation的内存管理规则:

  1. 创建函数(Create/Copy)返回的对象需要手动释放
  2. 获取函数(Get)返回的对象通常不需要释放
  3. 使用CFRetainCFRelease管理引用计数

跨平台兼容性

虽然Core Foundation主要是Apple平台的框架,但CoreFoundation-sys在设计上考虑了跨平台兼容性。在非Apple平台上,某些功能可能不可用或表现不同。

高级用法

与Rust标准类型的转换

use core_foundation_sys::string::*;
use std::ffi::CString;

unsafe {
    let rust_str = "Hello from Rust";
    let c_str = CString::new(rust_str).unwrap();
    
    let cf_str = CFStringCreateWithCString(
        std::ptr::null(), 
        c_str.as_ptr(), 
        kCFStringEncodingUTF8
    );
    
    // 使用cf_str...
    
    CFRelease(cf_str as *const _);
}

错误处理

use core_foundation_sys::base::*;

unsafe {
    let result = some_core_foundation_function();
    if result.is_null() {
        // 处理错误
        panic!("Core Foundation function failed");
    }
    // 使用result...
    CFRelease(result as *const _);
}

完整示例

下面是一个整合了字符串、数组和字典处理的完整示例:

use core_foundation_sys::{
    array::*,
    base::*,
    dictionary::*,
    number::*,
    string::*,
};

fn main() {
    unsafe {
        // 1. 字符串处理示例
        let cf_str = CFStringCreateWithCString(
            std::ptr::null(),
            "Rust CoreFoundation示例\0".as_ptr() as *const i8,
            kCFStringEncodingUTF8,
        );
        let length = CFStringGetLength(cf_str);
        println!("字符串长度: {}", length);

        // 2. 数组处理示例
        let array_values = [cf_str as *const _, cf_str as *const _];
        let cf_array = CFArrayCreate(
            std::ptr::null(),
            array_values.as_ptr(),
            array_values.len() as CFIndex,
            &kCFTypeArrayCallBacks,
        );
        let array_count = CFArrayGetCount(cf_array);
        println!("数组元素数量: {}", array_count);

        // 3. 字典处理示例
        let keys = [CFStringCreateWithCString(
            std::ptr::null(),
            "language\0".as_ptr() as *const i8,
            kCFStringEncodingUTF8,
        )];
        let values = [cf_str as *const _];
        
        let cf_dict = CFDictionaryCreate(
            std::ptr::null(),
            keys.as_ptr() as *const _,
            values.as_ptr() as *const _,
            1,
            &kCFTypeDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks,
        );
        
        // 释放所有资源
        CFRelease(keys[0] as *const _);
        CFRelease(cf_str as *const _);
        CFRelease(cf_array as *const _);
        CFRelease(cf_dict as *const _);
    }
}

总结

CoreFoundation-sys为Rust提供了与Apple系统底层API交互的能力,适合需要深度系统集成的应用开发。使用时需要注意内存管理和平台兼容性问题。

回到顶部