rust-bindgen
rust-bindgen copied to clipboard
objective-c generated classes should not implement `objc::Message`.
Input C/C++ Header
@interface MyClass
@end
Bindgen Invocation
$ bindgen input.h -- -x objective-c
Actual Results
...
#[repr(transparent)]
#[derive(Debug, Copy, Clone)]
pub struct MyClass(pub id);
...
unsafe impl objc::Message for MyClass {}
...
Expected Results
objc::Message should be implemented on types for which pointers to the type will accept messages. The types generated by bindgen are aliases of the basic object pointer type (*mut objc::runtime::Object), so implementing objc::Message is wrong and will always result in invalid memory access (e.g., a *const MyClass does not accept messages).
If bindgen were changed to generate classes which are intended to be cast from the basic object pointer type this would work, however such a change would be a breaking change for consumers.
That change would look something like
use objc::{self, class, msg_send, sel, sel_impl};
#[allow(non_camel_case_types)]
pub type id = *mut objc::runtime::Object;
#[repr(transparent)]
#[derive(Debug, Copy, Clone)]
pub struct MyClass;
impl std::ops::Deref for MyClass {
type Target = objc::runtime::Object;
fn deref(&self) -> &Self::Target {
&self
}
}
unsafe impl objc::Message for MyClass {}
impl MyClass {
pub fn alloc() -> *mut Self {
unsafe { msg_send!(class!(MyClass), alloc) }
}
}
impl IMyClass for *mut MyClass {}
pub trait IMyClass: Sized + std::ops::Deref {}
But that's not really in scope for this bug.