[generator] Support Kotlin's unsigned types (#539) #553
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes: #525
Context: dotnet/android#4054
Context: https://github.com/Kotlin/KEEP/blob/13b67668ccc5b4741ecc37d0dd050fd77227c035/proposals/unsigned-types.md
Context: https://kotlinlang.org/docs/reference/basic-types.html#unsigned-integers
Another place where Kotlin makes use of "name mangling" -- see also
commit f3553f4 -- is in the use of unsigned types such as
UInt
.At the JVM ABI level, Kotlin treats unsigned types as their signed
counterparts, e.g.
kotlin.UInt
is anint
andkotlin.UIntArray
is an
int[]
:Kotlin uses Java Annotations to determine whether a parameter or
return type is actually an unsigned type instead of a signed type.
Update
Xamarin.Android.Tools.Bytecode
andgenerator
to bind e.g.:kotlin.UInt
asSystem.UInt32
kotlin.UIntArray
as aSystem.UInt32[]
and likewise for the other unsigned types
ushort
,ulong
,ubyte
.In order to do this, we pretend that they are native Java types and
just translate a few places where we need to tell Java the real type.
~~ Xamarin.Android.Tools.Bytecode / class-parse ~~
When we read the Kotlin metadata in the Java bytecode, if we come
across one of these types we store it within an additional
FieldInfo.KotlinType
property that we can access later. When weare generating the XML we check this additional flag and if it's one
of our types we emit it instead of the native Java type.
For example:
Here we see that even though
@jni-return
isI
-- meaningint
--the
@return
property isuint
. Likewiseparameter/@jni-type
andparameter/@type
. The JNI ABI isint
, but we bind in C# asuint
.~~ ApiXmlAdjuster ~~
Update
JavaTypeReference
to contain unsigned types:~~ generator ~~
generator
has the 4 new types added to theSymbolTable
asSimpleSymbols
:There are 2 fixups we have to make because we use
GetIntValue(...)
,etc. instead of having unsigned versions:
GetIntValue()
instead of
GetUintValue()
.int
value returned touint
. This is accomplishedvia the new
ISymbol.ReturnCast
property.~~ A Note On API Compatibility ~~
Bindings which use Kotlin Unsigned Types will only work on
Xamarin.Android 10.2.0 or later ("Visual Studio 16.5").
The problem is that while we can emit C# source code which will
compile against older versions of Xamarin.Android, if they use
arrays they will not run under older versions of Xamarin.Android.
For example, imagine this binding code for the above Kotlin
Example.array()
method:That could conceivably compile against older Xamarin.Android
versions. However, that cannot run against older Xamarin.Android
versions, as eventually
JNIEnv.GetArray()
will hit somedictionaries to determine how to marshal
IntPtr
to auint[]
, atwhich point things will fail because there is no such mapping until
Xamarin.Android 10.2.0.
We feel that a "hard" ABI requirement will have more "graceful"
failure conditions than a solution which doesn't add ABI requirements.
In this case, if you create a Kotlin library binding which exposes
unsigned types, attempting to build an app in Release configuration
against older Xamarin.Android versions will result in a linker error,
as the required
JNIEnv
methods will not be resolvable.(cherry picked from commit 71afce5)