6 ms·
Interesting; I was wondering if they had added some magic feature to Clang to enable Objective-C in pure C++ mode, but no, it really is C++. It just directly c
by comex 5y ago
Interesting; I was wondering if they had added some magic feature to Clang to enable Objective-C in pure C++ mode, but no, it really is C++. It just directly calls the Objective-C runtime functions like sel_registerName, objc_lookUpClass, objc_msgSend, etc. The expensive lookups like sel_registerName are performed in initializers of global variables, whereas for 'real' Objective-C code the dynamic linker does essentially the same job itself. I believe this has the disadvantage that unused selectors can't be fully optimized out, as C++ doesn't allow removing global initializers even if the global in question is unused. Therefore, any program that includes this library will, at initialization time, look up all ~1100 selectors defined in the library, regardless of which ones the program actually uses. But besides that, this approach may have equal performance to native Objective-C.
Also - throwing a zip file over the fence, really? Can't you put it on GitHub?
- waynecochran 5y agoObjective-C++ is already supported so this is not a big step to bridge from C++ to Objective-C.
- raphlinus 5y agoAlong similar lines, from my skim of the README, it also seems like deallocated things are not actually released until the return from the nearest autorelease block, which is not exactly convenient for Rust (and it's not properly safe either without at least an extra retain). I always imagined that when you call through Swift it's a more native memory management interface, but perhaps it's also the same Obj-C layer under the hood.
- ash_gti 5y agoThe c++ wrappings break ARC, so if you use this library you'll have to manually retain/release any object. The autorelease pool is helpful if you autorelease an object but you'll need to manually manage the memory when using this set of helpers. In obj-c or swift, ARC would handle that for you, so this makes the memory management aspect of using Metal a bit more of a headache.
- raphlinus 5y agoRight. Would you happen to know if there's a way to make a retained object actually deallocate on last "release," other than putting an autorelease pool around it? Would you also happen to know if the Swift bindings have this same wonky autorelease behavior, or more straightforward Swift-style refcounting?
- comex 5y agoFrom a quick grep, it looks like this wrapper does not automatically call autorelease, so autorelease happens only when a method implementation autoreleases its own return value (or if you call autorelease yourself). Objective-C has a standard rule for when a method is supposed to autorelease its return value: to quote the metal-cpp readme, it's when "you create an object with a method that does not begin with `alloc`, `new`, `copy`, or `mutableCopy`". In many cases, these are convenience methods that also have equivalent "initWith" methods, e.g. [NSString stringWithFormat:@"%d", 42] is equivalent to [[[NSString alloc] initWithFormat:@"%d", 42] autorelease] But I'm not too familiar with Metal, and… it looks like Metal doesn't have very many of these methods in the first place. Instead it has a lot of 'new' methods, which shouldn't use autorelease. When a method does call autorelease, Swift doesn't have any way of getting around it, though if there are autoreleasing and alloc/init variants of the same method, it will prefer alloc/init. Other than that, Swift likes to use the function objc_retainAutoreleasedReturnValue [1], which may prevent the object from going on the autorelease pool (with the 'optimized return' magic), but only as a non-guaranteed optimization. [1] https://github.com/apple-opensource/objc4/blob/a367941bce42b1515aeb2cc17020c65e3a57fa20/runtime/NSObject.mm#L2158 https://github.com/apple-opensource/objc4/blob/a367941bce42b...
- raphlinus 5y agoThanks, this is helpful. The specific method that's causing me trouble right at the moment is "computeCommandEncoder"[1], which is a method off MTLCommandBuffer, and I think not in the "new" class. In the Rust bindings[2], this is just a msg_send! and from what I can tell is getting an autoreleased reference, not a retained one. It looks like objc_retainAutoreleasedReturnValue might be exactly what I'm looking for, even if it isn't 100% guaranteed; if I'm understanding, it would be safe, and wouldn't actually leak as long as you had an autorelease pool somewhere in the chain. However, I'm not seeing a binding to it in the objc crate[3]. Sounds like maybe I should file an issue? Also, given that such a method seems obviously useful, I wonder why it's not being called from these C++ bindings? [1]: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443044-computecommandencoder?language=objc https://developer.apple.com/documentation/metal/mtlcommandbu... [2]: https://github.com/gfx-rs/metal-rs/blob/master/src/commandbuffer.rs#L105 https://github.com/gfx-rs/metal-rs/blob/master/src/commandbu... [3]: https://docs.rs/objc/0.2.7/objc/runtime/index.html https://docs.rs/objc/0.2.7/objc/runtime/index.html
- lukeh 5y agoI suspect they didn't implement RAII because, in the intended usage, they expect the autorelease pool to be drained every frame.
- thurn 5y agoSomewhat unrelated, but is Rust `Arc` able to match the performance of Swift reference counting? I know they do a bunch of fancy tricks to embed the reference count into the pointer high bits, it seems like Rust would probably struggle to achieve that.
- pcwalton 5y agoInteresting. Rust does the same thing with Obj-C selectors, except each selector is looked up lazily at the first call. I wonder why they didn't do that for these bindings.
- denkmoon 5y ago> Can't you put it on GitHub? GitHub was not invented at Apple, sadly.
- bananabreakfast 5y agoSwift was, and that's on GitHub :)
- jb1991 5y agoSo? https://github.com/apple https://github.com/apple