use libloading::Library;
use std::sync::OnceLock;
pub struct Framework {
pub video_toolbox: Library,
pub core_video: Library,
pub core_media: Library,
pub core_foundation: Library,
}
static FRAMEWORK: OnceLock<Result<Framework, String>> = OnceLock::new();
pub fn framework() -> Result<&'static Framework, &'static str> {
FRAMEWORK
.get_or_init(load)
.as_ref()
.map_err(|s| s.as_str())
}
fn load() -> Result<Framework, String> {
let video_toolbox = open("/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")?;
let core_video = open("/System/Library/Frameworks/CoreVideo.framework/CoreVideo")?;
let core_media = open("/System/Library/Frameworks/CoreMedia.framework/CoreMedia")?;
let core_foundation =
open("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")?;
Ok(Framework {
video_toolbox,
core_video,
core_media,
core_foundation,
})
}
fn open(path: &str) -> Result<Library, String> {
unsafe { Library::new(path) }.map_err(|e| format!("dlopen {path}: {e}"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn frameworks_load() {
let fw = framework().expect("framework load");
let _: libloading::Symbol<unsafe extern "C" fn()> = unsafe {
fw.video_toolbox
.get(b"VTDecompressionSessionCreate\0")
.expect("VTDecompressionSessionCreate symbol")
};
let _: libloading::Symbol<unsafe extern "C" fn()> = unsafe {
fw.core_foundation
.get(b"CFRetain\0")
.expect("CFRetain symbol")
};
}
}