Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Oct 3, 2023
1 parent 96f4d52 commit 3d170b5
Show file tree
Hide file tree
Showing 33 changed files with 1,009 additions and 2,010 deletions.
39 changes: 15 additions & 24 deletions crates/objc2/examples/class_with_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,19 @@
use std::marker::PhantomData;
use std::sync::Once;

use objc2::declare::{ClassBuilder, Ivar, IvarEncode, IvarType};
use objc2::declare::ClassBuilder;
use objc2::mutability::Mutable;
use objc2::rc::Id;
use objc2::runtime::{AnyClass, NSObject, Sel};
use objc2::{msg_send, msg_send_id, sel};
use objc2::{ClassType, Encoding, Message, RefEncode};

/// Helper type for the instance variable
struct NumberIvar<'a> {
// Doesn't actually matter what we put here, but we have to use the
// lifetime parameter somehow
p: PhantomData<&'a mut u8>,
}

unsafe impl<'a> IvarType for NumberIvar<'a> {
type Type = IvarEncode<&'a mut u8>;
const NAME: &'static str = "_number_ptr";
}

/// Struct that represents our custom object.
#[repr(C)]
pub struct MyObject<'a> {
// Required to give MyObject the proper layout
superclass: NSObject,
// SAFETY: The ivar is declared below, and is properly initialized in the
// designated initializer.
//
// Note! Attempting to acess the ivar before it has been initialized is
// undefined behaviour!
number: Ivar<NumberIvar<'a>>,
p: PhantomData<&'a mut u8>,
}

unsafe impl RefEncode for MyObject<'_> {
Expand All @@ -50,8 +33,12 @@ impl<'a> MyObject<'a> {
) -> Option<&'s mut Self> {
let this: Option<&mut Self> = unsafe { msg_send![super(self), init] };
this.map(|this| {
// Properly initialize the number reference
Ivar::write(&mut this.number, ptr.expect("got NULL number ptr"));
let ivar = Self::class().instance_variable("number").unwrap();
// SAFETY: The ivar is added with the same type below
unsafe {
ivar.load_ptr::<&mut u8>(&this.superclass)
.write(ptr.expect("got NULL number ptr"))
};
this
})
}
Expand All @@ -63,11 +50,15 @@ impl<'a> MyObject<'a> {
}

pub fn get(&self) -> &u8 {
&self.number
let ivar = Self::class().instance_variable("number").unwrap();
// SAFETY: The ivar is added with the same type below, and is initialized in `init_with_ptr`
unsafe { *ivar.load::<&mut u8>(&self.superclass) }
}

pub fn set(&mut self, number: u8) {
**self.number = number;
let ivar = Self::class().instance_variable("number").unwrap();
// SAFETY: The ivar is added with the same type below, and is initialized in `init_with_ptr`
unsafe { **ivar.load_mut::<&mut u8>(&mut self.superclass) = number };
}
}

Expand All @@ -84,7 +75,7 @@ unsafe impl<'a> ClassType for MyObject<'a> {
let superclass = NSObject::class();
let mut builder = ClassBuilder::new(Self::NAME, superclass).unwrap();

builder.add_static_ivar::<NumberIvar<'a>>();
builder.add_ivar::<&mut u8>("number");

unsafe {
builder.add_method(
Expand Down
15 changes: 15 additions & 0 deletions crates/objc2/src/__macro_helpers/common_selectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,18 @@ pub fn new_sel() -> Sel {
pub fn dealloc_sel() -> Sel {
__sel_inner!(__sel_data!(dealloc), "dealloc")
}

/// An undocumented selector called by the Objective-C runtime when
/// initalizing instance variables.
#[inline]
#[allow(dead_code)] // May be useful in the future
fn cxx_construct_sel() -> Sel {
__sel_inner!(".cxx_construct\0", ".cxx_construct")
}

/// An undocumented selector called by the Objective-C runtime when
/// deinitalizing instance variables.
#[inline]
pub(crate) fn cxx_destruct_sel() -> Sel {
__sel_inner!(".cxx_destruct\0", ".cxx_destruct")
}
32 changes: 13 additions & 19 deletions crates/objc2/src/__macro_helpers/declare_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ use core::marker::PhantomData;
#[cfg(all(debug_assertions, feature = "verify"))]
use std::collections::HashSet;

use crate::declare::ClassBuilder;
use crate::encode::{Encode, Encoding};
use crate::rc::{Allocated, Id};
use crate::runtime::{AnyClass, AnyObject, MessageReceiver, MethodImplementation, Sel};
#[cfg(all(debug_assertions, feature = "verify"))]
use crate::runtime::{AnyProtocol, MethodDescription};
use crate::{ClassType, DeclaredClass, Message, ProtocolType};

use objc2_encode::Encoding;

use crate::declare::{ClassBuilder, IvarType};
use crate::encode::Encode;
use crate::rc::{Allocated, Id};
use crate::runtime::{AnyClass, MethodImplementation, Sel};
use crate::runtime::{AnyObject, MessageReceiver};
use crate::{ClassType, Message, ProtocolType};

use super::declared_ivars::{register_with_ivars, setup_ivars};
use super::{CopyOrMutCopy, Init, MaybeUnwrap, New, Other};
use crate::mutability;

Expand Down Expand Up @@ -213,18 +210,20 @@ fn failed_declaring_class(name: &str) -> ! {
panic!("could not create new class {name}. Perhaps a class with that name already exists?")
}

impl<T: ?Sized + ClassType> ClassBuilderHelper<T> {
impl<T: ?Sized + DeclaredClass> ClassBuilderHelper<T> {
#[inline]
#[track_caller]
pub fn new() -> Self
where
T::Super: ClassType,
{
let builder = match ClassBuilder::new(T::NAME, <T::Super as ClassType>::class()) {
let mut builder = match ClassBuilder::new(T::NAME, <T::Super as ClassType>::class()) {
Some(builder) => builder,
None => failed_declaring_class(T::NAME),
};

setup_ivars::<T>(&mut builder);

Self {
builder,
p: PhantomData,
Expand Down Expand Up @@ -288,13 +287,8 @@ impl<T: ?Sized + ClassType> ClassBuilderHelper<T> {
}

#[inline]
pub fn add_static_ivar<I: IvarType>(&mut self) {
self.builder.add_static_ivar::<I>()
}

#[inline]
pub fn register(self) -> &'static AnyClass {
self.builder.register()
pub fn register(mut self) -> (&'static AnyClass, isize, isize) {
register_with_ivars::<T>(self.builder)
}
}

Expand All @@ -321,7 +315,7 @@ pub struct ClassProtocolMethodsBuilder<'a, T: ?Sized> {
registered_class_methods: HashSet<Sel>,
}

impl<T: ?Sized + ClassType> ClassProtocolMethodsBuilder<'_, T> {
impl<T: ?Sized + DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
#[inline]
pub unsafe fn add_method<F>(&mut self, sel: Sel, func: F)
where
Expand Down
Loading

0 comments on commit 3d170b5

Please sign in to comment.