Thanks for moving the discussion to the forums, it’s good to gather some more input on these decisions.
Thanks for chiming in @andriydruk! I see you’re also doing the cached wrappers AFAICS with the UInt8Enum. We have something similar called the “wrapper” mode, that we discussed a while back, it’s an opt in mode that wraps the unsigned types as their Guava unsigned equivalents – having that said, we don’t currently have users of that mode as far as I can tell.
We also already have support for making jextracted methods and parameters as @Unsigned, which we should continue/expand to cover the arrays/generic types which contain unsigned numbers.
Today, a method like:
// swift
public func unsignedLong(first: UInt64, second: UInt32) -> UInt32
is extracted as:
@Unsigned
public static int unsignedLong(@Unsigned long first, @Unsigned int second) {
This already works in ffm and also jni mode.
So the printMyAgeexample @madsodgaard provided in the OP would actually already be @Unsigned marked, giving developers that hint.
Side note: Technically we also have a “wrap” mode in FFM, where unsigned types are represented as their Guava
UnsignedIntegerequivalents. That’s of course expensive because of the objects, and more annoying to work with bit it was a direction that we explored. Currently I don’t think this mode is being used by any adopters though, the performance aspect wins people over to the just “watch out what you’re doing” side.
So to summarize the status quo of the FFM mode:
Foundation.Data- which was driven by SwiftCrypto APIs accepting that type,- and
UnsafeRawBufferPointerare supported as well though ofc “unsafe”.
And, something I put together just now as I wanted to remind myself this piece of the sourcegen to have an informed opinion for this discussion…
- [new]
[UInt8]- partial impl over here- however, this isn’t quite good yet… as it incurs 2 copies, into a memory segment, and then into a Swift array… instead we should be directly creating a native instance of a Swift array from Java and we can do that.
Long story short, I thought about this throughout the day and I think the approach we want to take here is should fall out of what we’re already doing for unsigned numbers:
- I agree that we should just extract as the “bit-width” integer type (
byte[]) - We should also “annotate” about the unsignedness with
@Unsigned- i.e. the same way we do
@Unsigned byte parmwe should get@Unsigned byte[] byteswhich represents “this wasUInt8" - We also have source documentation which method a Java binding will be calling, so this also is documenting that the target is an UIntN-array method.
- i.e. the same way we do
Then we should keep digging here and provide direct support for Data as the FFM mode does already because it then enables less copying if the target native method already is accepting Data.
This would be also great to support in swift-java of course. Would one of you be willing to help out and contribute some of that support back upstream @marcprux @andriydruk? We’d love to get some collaboration that benefits Android but also others going here, so if you have some things already here, that seems like perhaps a good one to start with?
I’m not sure about importing Data “as” ByteBuffer, given that we can just return a Data wrapper on the Java side – however if we could add a simple “from Data → ByteBuffer” conversions in the runtime library I’m sure folks would love this ![]()
The actual end-game here I feel will be Span on the Swift side since it is somewhat more flexible than Data, so I think that’s the end goal we should be looking at next, unless Marc or someone can help contributing some byte buffer mappings as well.
In the end, it’s good to have a wide range of supported types, so I guess we’ll want all of them eventually…