#1444 Native peer can't return String[]

KevinKelley Thu 10 Mar 2011

Java FFI docs say that arrays of objects map to Fantom List of appropriate type, but I can't get it to work. Tried variations on nullable, but no luck...

An example:

Ffi.fan

class Ffi
{
  native Str passes()
  native Str?[]? fails()

  Void main() { echo(passes); echo(fails); }
}

FfiPeer.java

package fan.klk;
public class FfiPeer
{
  public static FfiPeer make(fan.klk.Ffi self) { return new FfiPeer(); }

  public String passes(fan.klk.Ffi self) { return "works"; }

  public String[] fails(fan.klk.Ffi self) { String[] ss = {"f","a","i","l","s"}; return ss; }
}

build.fan

using build
class Build : BuildPod
{
  new make()
  {
    podName = "klk"
    summary = "test FFI returning String[]"
    version = Version("1.0")
    depends = ["sys 1.0", "build 1.0"]
    srcDirs = [`./`]
    javaDirs= [`./`]
  }

}

building that and running, yields:

>fan klk::Ffi works sys::Err: java.lang.NoSuchMethodError: fan.klk.FfiPeer.fails(Lfan/klk/Ffi;)Lfan/ sys/List;

klk::Ffi.fails (Ffi.fan)
klk::Ffi.main (Ffi.fan:8)
java.lang.reflect.Method.invoke (Unknown)
fan.sys.Method.invoke (Method.java:552)
fan.sys.Method$MethodFunc.callOn (Method.java:230)
fan.sys.Method.callOn (Method.java:139)
fanx.tools.Fan.callMain (Fan.java:137)
fanx.tools.Fan.executeType (Fan.java:102)
fanx.tools.Fan.execute (Fan.java:38)
fanx.tools.Fan.run (Fan.java:250)
fanx.tools.Fan.main (Fan.java:288)

kaushik Thu 10 Mar 2011

Did you try returning fan.sys.List instead of String[] in FfiPeer.java?

KevinKelley Thu 10 Mar 2011

Yes, changing the peer method to

public fan.sys.List fails(fan.klk.Ffi self) { return null; }

works, but leaves me needing to manually create and fill the fan.sys.List from the Java array. Maybe I'm being dense -- the fandoc I quoted sounds as though there's an automatic mapping for that, and I'm not seeing how to trigger it.

peter Thu 10 Mar 2011

One approach that works for me is (assuming you import fan.sys.*):

public List fails(fan.klk.Ffi self) { 
  String[] ss = {"f","a","i","l","s"}; 
  return new List(Type.of(ss[0]), ss); 
}

and then in the Fantom code:

native Str[] fails

The non-list/array types seem to convert automatically. Also the primitive-array types. But I also fail to have an object-list/array type convert automatically, without something like the above.

brian Thu 10 Mar 2011

Kevin,

A native method is a different beast than Java FFI. So if a native method returns Str[], then your implementation must return the exact Fantom representation of that type which is List(Sys.StrType, ...).

Think about it like this:

  • a class with native methods must look exactly like any other Fantom class, there is never any translation
  • a Java FFI class on the other hand might do all sorts of translations, boxing, or unboxing

KevinKelley Thu 10 Mar 2011

@Peter, thanks, that's the invocation I needed; manually constructing the wrapper list under the covers. That works.

@Brian, in the Natives overview, there's a sentence saying "see Java FFI to map between Fantom and Java types", and I was trying to language-lawyer my way into having my cake and eating it too. :-)

Thanks for the good comments.

Login or Signup to reply.