Closed marcpabst closed 1 week ago
I think I will need to revise this question - turns out this is probbaly related with how Objective C handled SIMD types. I will close this one (tho I think this librry still lacks examples) and open a new one.
Well, it does say in the docs for msg_send!
:
All arguments, as well as the return type, must implement
Encode
And SimdFloat4
doesn't, because you haven't implemented that trait.
But I definitely recognize that this is not visible, and there should be some more introductory-level docs for this!
I think I was a bit tired and frustrated when writing this, my aplogies for that. I actually tried implementing Encode
, but the code I copied in here is objc
code (which actually works as intended). But as it turns out, SimdFloat4
is super opaque and apple seems to do some funny things under the hood. I only managed to get the first column out, the rest is all gibberish.
Now using some ObjectiveC glue code (basically reading all elements out and creating an array from that on the Objective C side) it works. But maybe worth keeping in mind when support for simd
types is added!
I think I was a bit tired and frustrated when writing this, my aplogies for that
No problem, it didn't register as rude to me.
I actually tried implementing
Encode
Huh, yeah, I see what you mean, Encoding
can't actually represent the encoding of SIMD types, as they don't actually have an encoding (@encode(simd_float4) == ""
and @encode(simd_float4x4) == "{?=[4]}"
, which our encoding routines can't handle).
This may actually a problem ABI-wise, because we use the encoding as part of figuring out the correct calling convention; but then again, a type like typedef __attribute__((__ext_vector_type__(1))) long double simd_longdouble;
also breaks in Clang, so maybe it's not really an issue in practice.
I'll reopen this until I've investigated things a bit more, this is an issue that should be fixed.
Just to add some context, using objc
I can get the first column of the matrix by "lying" and telling msg_send!
I'm expecting a [f32, 4]
array (or something memory-equivalent). But when I tell msg_send!
I want a [f32, 16]
, it all breaks and all values are off.
From my reading of Clang's source code, the ABI expects us to use objc_msgSend
and not objc_msgSend_stret
in the following cases:
AAPCS16_VFP
ABI (maybe some kind of floating point vectors?).objc_msgSend_stret
?objc_msgSend
.Though the code is quite involved, and I glossed over a lot of the details.
But it does seem like vector types at the very least need some sort of different handling to have the correct message-sending ABI. I don't know how vector types relate to SIMD, but they sound similar, so maybe SIMD types do also use a different ABI?
Yep, that's what I saw as well. I'm on aarch64
(iPad/MacBook Pro M2), so objc_msgSend
should be the way to go, Does msg_send!
default to objc_msgSend_stret
?
msg_send!
picks the right message sending function based on the return type, see:
https://github.com/madsmtm/objc2/blob/155edc19bb3f1f3851679b277ad321cda4db365a/crates/objc2/src/runtime/message_receiver.rs#L53-L154
But I think this logic is subtly wrong for vector types, and that's what I want to fix.
All of this is only tangentially related to your problem of not being able to implement Encode
correctly, and then panicking, that part should be fairly easy to solve.
But I tried with the objc
crate that I assume used the same or simmiliar logics (but lacks the verification of encodings by default) - I presume this might be related to the way structs are handled?
I actually suspect the code example you provided might technically be wrong too on Aarch64, as the ABI of SIMD types isn't the same as the ABI of a C struct - it happens to work since you use the large simd_float4x4
, but passing a type like simd_float4
across an ABI boundary requires you to use the corresponding Simd<f32, 4>
/ core::arch::aarch64::float32x4_t
.
In general, I'm unsure of the state of SIMD FFI support? There's feature(simd_ffi)
, but that hasn't gotten far.
Re examples: There are some in objc2::encode
, but is there another place where it would have been more visible / more easily understandable?
I think the examples are quite good already, but as some point it might be worth to add a short user guide / getting started page and then link to the examples.
I've added Encoding::None
in https://github.com/madsmtm/objc2/pull/584 to allow you to specify when Clang doesn't emit an encoding for a type, no timeline on a release.
Note that this does not mean that objc2
officially supports SIMD types; the wrong message-sending function may still be chosen, and Rust's own support for it is yet lacking.
Great, thank you! I haven't looked into this for a while but will definitely come back to this shortly for an ongoing project.
I'm attempting to use
objc2
for Apple iOS API interoperability, and I'm really struggling with basic tasks, such as retrieving an Objective-C struct (simd_float4x4, https://developer.apple.com/documentation/arkit/aranchor/2867981-transform?language=objc) from an object into Rust. Naively, I assumed this would work, but it doesn't:and then
Could we have some more examples for things like this?