#405 Java FFI - Mapping primitive arrays

brian Mon 24 Nov 2008

I've got Object array coercion working to/from sys::List when calling out to Java methods:

Java => Fan:  List.make(javaType, array)
Fan => Java:  (Foo[])list.asArray()

The javaType is an instance of sys::Type for the Java class accessed as a static field on the pod class (like Duration and Uri literals). So mapping to and from Java is just a few instructions and pretty efficient.

The last big piece before tackling subclassing is how to map primitive arrays. These can't be mapped efficiently to sys::List since List assumes Object[] storage and Object access.

My thoughts for mapping primitive arrays is to just provide wrapper classes under fanx.interop which can be used as normal Java FFI classes with implicit coercion:

  • BooleanArray
  • ByteArray
  • ShortArray
  • CharArray
  • IntArray
  • LongArray
  • FloatArray
  • DoubleArray

These classes would all support a get, set, and size method to work just like List, except it would be optimized for longs/doubles to avoid any boxing:

ShortArray
{
   Int get(Int index)
   Void set(Int index, Int val)
   Int size()
}

I would suggest indexing work like List with the ability to use negative indices to access from the end of the list.

helium Mon 24 Nov 2008

I know the topic is Java FFI not .Net FFI, but anyway: will there be special arrays for .Net CLS-compliant types?

CLS compliant types that are value types are: System.Byte, System.Int16, System.Int32, System.Int64, System.Single, System.Double, System.Boolean, System.Char, System.Decimal and System.IntPtr.

Java's short and .Net's System.Int16 are the same, Java's int and .Net's System.Int32 are the same, ... .

Are the more technical .Net names (Int16, Int32, ...) perhaps better than the C-like vague names short, long, ... ?

brian Mon 24 Nov 2008

I know the topic is Java FFI not .Net FFI, but anyway: will there be special arrays for .Net CLS-compliant types?

I was thinking about that also, and of course we would do something similiar for .NET.

One of things I was considering is that maybe we create portable APIs for representing arrays which then map to both Java and .NET arrays under the covers. The only different is that .NET has some unsigned primitives also - but those can similuated in Java with the right bitmasking.

Although I don't think we would ever do IntPtr - I thought using unmanaged pointers in a public API was against common language guidelines?

So I'm a bit on the fence on whether we try to do arrays in a portable manner. The two choices would be:

  1. [java]fanx.interop and [dotnet]Fanx.Interop
  2. some portable Fan pod (probably not sys), maybe arrays or collections

helium Mon 24 Nov 2008

The unsigned types are not CLS-compliant. I don't think we need to support those types. See http://msdn.microsoft.com/en-us/library/12a7a7h3.aspx for further details.

(BTW, the site seems currently almost unusably slow.) (edit: now it's fast again)

brian Wed 26 Nov 2008

I've been debating myself (that happens often) on whether arrays are a portable Fan API or specific to each FFI port (Java or .NET). I think I've finally decided that they should be specific to a FFI at least for now. Given that I'm going to stick with my original plan that arrays map to Java as follows:

boolean[] => [java] fanx.interop::BooleanArray
byte[]    =>  [java] fanx.interop::ByteArray
short[]   =>  [java] fanx.interop::ShortArray
char[]    =>  [java] fanx.interop::CharArray
int[]     =>  [java] fanx.interop::IntArray
long[]    =>  [java] fanx.interop::LongArray
float[]   =>  [java] fanx.interop::FloatArray
double[]  =>  [java] fanx.interop::DoubleArray

Since we are mapping them directly to Java (versus as a portable API), I think we should use classnames which reflect their Java name.

Under the covers these arrays won't be boxed, but rather passed directly (like we do Bool, Int, Float, and Str).

Andrey Zakharov Mon 26 Nov

Hi, I've got [java] fanx.interop::IntArray from Java layer (int[]) and want to utilize fantom routing List.map(",") for it. How could I achieve this? Thanx for advance.

SlimerDude Tue 27 Nov

Hi Andrey, I don't really understand your question as List.map(...) takes a closure not a string. (Did you mean List.join(...)?)

But as you've probably already figured out, fanx.interop::IntArray is really basic and doesn't offer any functional operations. To use the convenient List methods, you'll have to create a new List object and copy the contents of IntArray over.

Note that by doing so, I believe all ints will be converted to longs. If it's imperative that you keep the ints or if the performance hit is too much then you'll have to write some native Java code instead.

Login or Signup to reply.