rust-bindgen
rust-bindgen copied to clipboard
Added Objc category inheritance
This closes #1779.
This is done by adding:
items_mutonBindgenContextwhich is justiter_muton the items because a category needs to modify an item to add the name of a category, and the template names from that category. This method most certainly results in very very bad performance but I really don't know how to get a reference to theObjCInterfaceusing just a name. So :/- The category name and template names are added to the ObjCInterface as
Vec<(String, Vec<String>)>. I'm open to making this a struct, I just kinda don't know what to call it.
I originally had the categories field as a Vec<Box<ObjCInterface>> and then clone()ed the interface after it was finished being built. You can see what that's like here. It required deriving Clone on ObjCInterface, ObjCMethod, and FuncionSig. I think Vec<(String, Vec<String>)> is cleaner but still a bit gross.
I also noticed that there's a lot of the templates when generating bindings. Here's an example for the Foundation Framework. So, I added a bunch of tests for the different inheritance cases - categories, templates, and categories that are templates.
Warning
- These commits modify unsafe code. Please review it carefully!
I've tried a few things to use Vec<ItemId>s as the category identifiers rather than a Vec<String, Vec<String>>
let category_id : ItemId = Item::from_ty_or_ref(c.cur_type(), c, None, ctx).into()
it actually turns out to be the id of the class (the real_interface id that is) I want to modify which is neat. (More on that later).
If I do:
let category_id : ItemId = Item::from_ty_or_ref(cursor.cur_type(), *cursor, None, ctx).into()
it segfaults which is neat.
If I do:
let category_id : ItemId = Item::from_ty_or_ref(cursor.cur_type(), c, None, ctx).into()
it returns an opaque type for that id when I try to do generation.
So, I'm not sure how to get the ItemId for the category. Thoughts?
I don't know enough about objective-c categories, but iterating all the items like that is not acceptable.
let real_interface_id : ItemId = Item::from_ty_or_ref(c.cur_type(), c, None, ctx).into()
yields the ItemId to the interface that we actually want to modify which is pretty cool. I'm having trouble trying to borrow mutability for it though. Do you have advice on doing that?
it segfaults which is neat.
What's the stack for that? It might be that you're overflowing the stack.
yields the ItemId to the interface that we actually want to modify which is pretty cool. I'm having trouble trying to borrow mutability for it though. Do you have advice on doing that?
Why do you need to mutably borrow it?
What's the stack for that? It might be that you're overflowing the stack.
Yeah, after a adding some debug statements, it looks like that call ends up overflowing the stack. Though, it doesn't yield a stack trace nor a normal rust error like thread 'main' has overflowed its stack. I'm guessing because it's blowing the stack someplace in clang? I'm up to look more into this if it sounds like a bug.
In hindsight, I forgot to answer this question:
Is there a way you can inspect the categories from the clang ast while parsing the original interface?
Hmm. https://clang.llvm.org/doxygen/structclang_1_1serialization_1_1ObjCCategoriesInfo.html#details seems promising. I'm not sure how to use it though.
Why do you need to mutably borrow it?
If we can't get the list of categories while parsing the original class, the only way I think we can get the categories: Vec<ItemId> (or equivalent) is to modify the original class when parsing the category.
@emilio Mind reviewing this PR again? I've been playing around with this branch combined with #1847 and the bindings generated are becoming kinda awesome. In my uikit-sys crate UIButton, all the trait implementations for with underscores are from categories and there are about 50 of them.
@scoopr are you available for a review? This PR adds a key feature to bindgen for objective-c support.
I did a fairly quick look at the diff, and from what I gather it looks good to me! Can't really comment on the specifics of the implementation as I'm not too familiar with that anymore. The expectation test result look great to me :)
:umbrella: The latest upstream changes (presumably 4f714ab79eb0ddff7b84ac0ec5487a6b347b3b90) made this pull request unmergeable. Please resolve the merge conflicts.
So here's a thought, is there any reason we can't just implement this when generating code for the
ObjCInterface?It feels weird that stuff that would be blacklisted would implement these traits and so on. It should also avoid the weird lookup, right?
As in, instead of keeping the category as a String in the interface, you would keep the ItemId. Then when doing code generation you can do the lookup just fine.
After some messing around with trying to make categories be an ItemId, I'm not sure how to move forward. I've been trying to uselet item = Item::from_ty_or_ref(cursor.cur_type(), cursor, None, ctx); in ObjCInterface::from_ty which segfaults. I think this is because Item::from_ty_or_ref someplace down the line calls ObjCInterface::from_ty and so we end up with infinite recursion (I've added debug statements to back this up).
Anyway, @emilio thoughts on the way forward?
:umbrella: The latest upstream changes (presumably 11ae35089e4748b7e2a6f50f6bef7709af72e724) made this pull request unmergeable. Please resolve the merge conflicts.
:umbrella: The latest upstream changes (presumably #2284) made this pull request unmergeable. Please resolve the merge conflicts.