mtl_gpu/library/
dynamic_library.rs1use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::Referencing;
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9#[repr(transparent)]
16pub struct DynamicLibrary(pub(crate) NonNull<c_void>);
17
18impl DynamicLibrary {
19 #[inline]
25 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
26 NonNull::new(ptr).map(Self)
27 }
28
29 #[inline]
31 pub fn as_raw(&self) -> *mut c_void {
32 self.0.as_ptr()
33 }
34
35 pub fn device(&self) -> crate::Device {
39 unsafe {
40 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(device));
41 if ptr.is_null() {
42 panic!("dynamic library has no device");
43 }
44 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
45 crate::Device::from_raw(ptr).expect("dynamic library has no device")
46 }
47 }
48
49 pub fn label(&self) -> Option<String> {
53 unsafe {
54 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
55 if ptr.is_null() {
56 return None;
57 }
58 let utf8_ptr: *const std::ffi::c_char =
59 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
60 if utf8_ptr.is_null() {
61 return None;
62 }
63 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
64 Some(c_str.to_string_lossy().into_owned())
65 }
66 }
67
68 pub fn set_label(&self, label: &str) {
72 if let Some(ns_label) = mtl_foundation::String::from_str(label) {
73 unsafe {
74 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
75 }
76 }
77 }
78
79 pub fn install_name(&self) -> Option<String> {
83 unsafe {
84 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(installName));
85 if ptr.is_null() {
86 return None;
87 }
88 let utf8_ptr: *const std::ffi::c_char =
89 mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
90 if utf8_ptr.is_null() {
91 return None;
92 }
93 let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
94 Some(c_str.to_string_lossy().into_owned())
95 }
96 }
97
98 pub fn serialize_to_url(
102 &self,
103 url: &mtl_foundation::Url,
104 ) -> Result<(), mtl_foundation::Error> {
105 unsafe {
106 let mut error: *mut c_void = std::ptr::null_mut();
107 let success: bool = mtl_sys::msg_send_2(
108 self.as_ptr(),
109 sel!(serializeToURL: error:),
110 url.as_ptr(),
111 &mut error as *mut _,
112 );
113 if success {
114 Ok(())
115 } else if !error.is_null() {
116 let _: *mut c_void = msg_send_0(error, sel!(retain));
117 Err(mtl_foundation::Error::from_ptr(error)
118 .expect("error pointer should be valid"))
119 } else {
120 Err(
121 mtl_foundation::Error::error(std::ptr::null_mut(), -1, std::ptr::null_mut())
122 .expect("failed to create error object"),
123 )
124 }
125 }
126 }
127}
128
129impl Clone for DynamicLibrary {
130 fn clone(&self) -> Self {
131 unsafe {
132 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
133 }
134 Self(self.0)
135 }
136}
137
138impl Drop for DynamicLibrary {
139 fn drop(&mut self) {
140 unsafe {
141 msg_send_0::<()>(self.as_ptr(), sel!(release));
142 }
143 }
144}
145
146impl Referencing for DynamicLibrary {
147 #[inline]
148 fn as_ptr(&self) -> *const c_void {
149 self.0.as_ptr()
150 }
151}
152
153unsafe impl Send for DynamicLibrary {}
154unsafe impl Sync for DynamicLibrary {}
155
156impl std::fmt::Debug for DynamicLibrary {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 f.debug_struct("DynamicLibrary")
159 .field("label", &self.label())
160 .field("install_name", &self.install_name())
161 .finish()
162 }
163}