Fix leak in generated iOS FFI wrappers by holding Retained<AnyObject>
This commit is contained in:
1 parent
57d6794ad6
commit
6adf7ba465
1 file changed
+18
-9
@@ -724,10 +724,10 @@ impl FfiBridgeParser {
|
|||||||
let class_name_bytes = format!("{}\0", name);
|
let class_name_bytes = format!("{}\0", name);
|
||||||
|
|
||||||
let type_def = quote! {
|
let type_def = quote! {
|
||||||
/// Opaque wrapper around an Objective-C object pointer
|
/// Opaque wrapper around a retained Objective-C object
|
||||||
/// The actual Swift class is looked up dynamically at runtime after dx links everything
|
/// The actual Swift class is looked up dynamically at runtime after dx links everything
|
||||||
pub struct #name {
|
pub struct #name {
|
||||||
inner: *mut manganis::objc2::runtime::AnyObject,
|
inner: manganis::objc2::rc::Retained<manganis::objc2::runtime::AnyObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for #name {}
|
unsafe impl Send for #name {}
|
||||||
@@ -827,17 +827,26 @@ impl FfiBridgeParser {
|
|||||||
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![class, alloc];
|
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![class, alloc];
|
||||||
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![instance, init];
|
let instance: *mut manganis::objc2::runtime::AnyObject = manganis::objc2::msg_send![instance, init];
|
||||||
|
|
||||||
if instance.is_null() {
|
// `alloc` + `init` returns a +1 retained object; `Retained::from_raw`
|
||||||
return Err("Failed to initialize instance");
|
// takes over that reference and sends `release` on drop.
|
||||||
}
|
let inner = manganis::objc2::rc::Retained::from_raw(instance)
|
||||||
|
.ok_or("Failed to initialize instance")?;
|
||||||
|
|
||||||
Ok(Self { inner: instance })
|
Ok(Self { inner })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create from an existing object pointer
|
/// Create from an existing object pointer.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `ptr` must be a valid, non-null pointer to an Objective-C object,
|
||||||
|
/// and the caller must transfer ownership of one retain count (+1)
|
||||||
|
/// to the returned wrapper, which sends `release` on drop.
|
||||||
pub unsafe fn from_raw(ptr: *mut manganis::objc2::runtime::AnyObject) -> Self {
|
pub unsafe fn from_raw(ptr: *mut manganis::objc2::runtime::AnyObject) -> Self {
|
||||||
Self { inner: ptr }
|
let inner = manganis::objc2::rc::Retained::from_raw(ptr)
|
||||||
|
.expect("from_raw called with a null pointer");
|
||||||
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -960,7 +969,7 @@ impl FfiBridgeParser {
|
|||||||
|
|
||||||
// Build the msg_send call
|
// Build the msg_send call
|
||||||
let this_expr = if func.receiver.is_some() {
|
let this_expr = if func.receiver.is_some() {
|
||||||
quote! { this.inner }
|
quote! { manganis::objc2::rc::Retained::as_ptr(&this.inner) as *mut manganis::objc2::runtime::AnyObject }
|
||||||
} else {
|
} else {
|
||||||
// For static methods, we'd need the class
|
// For static methods, we'd need the class
|
||||||
quote! { class }
|
quote! { class }
|
||||||
|
|||||||
Reference in new issue
Block a user