madsmtm / objc2

Bindings to Apple's frameworks in Rust
https://docs.rs/objc2/
MIT License
280 stars 35 forks source link

Generating Objective-C bindings to Rust-declared ObjC classes #583

Closed chyyran closed 3 months ago

chyyran commented 3 months ago

Hi, I'm looking to export an Objective-C API that deals with id and protocol objects. Things seem to work great within Rust land and my crate is using icrate and objc definitions, everything works very well but I'd like to expose my functionality to non-Rust users building their apps with Swift or Objective-C.

I first thought about writing a C API, but taking *const ProtocolObject<dyn T> for example didn't seem like the correct approach. Is there a way to export an objective-C API from Rust?

madsmtm commented 3 months ago

Hmm, are you defining your own classes with declare_class!, or just consuming Objective-C objects?

madsmtm commented 3 months ago

As an example, you could fairly easily export a function that takes Objective-C types. If you would like to return objects to Objective-C, it's a bit more complicated as then you have to deal with memory management rules, but it should also be doable.

// foo.rs

#[no_mange]
extern "C" fn my_function(obj: &AnyObject, protocol_obj: &ProtocolObject<dyn NSCopying>) {
    println!("{obj:?} {protocol_obj:?}");
}
// foo.c
void my_function(id obj, id<NSCopying> protocol_obj);
madsmtm commented 3 months ago

Maybe I can make things a bit more clear with a table:

Objective-C Rust argument Rust return
id &AnyObject Id<AnyObject>
id<NSCopying> &ProtocolObject<dyn NSCopying> Id<ProtocolObject<dyn NSCopying>>
NSObject* &NSObject Id<NSObject>
Class &AnyClass &'static AnyClass
chyyran commented 3 months ago

Thanks, that table is very useful. I was able to just publish regular C headers that take id<T>, where on the Rust side they take *const ProtocolObject<dyn T>.