#898 error - using [java] fan.sys

liamstask Wed 6 Jan 2010

I was trying to make use of SysInStream via the java FFI, and found that when I tried to add a using declaration for the [java] fan.sys package, I got the following error:

ERR: Internal compiler error
sys::UnknownTypeErr: sys::FanObj
  fan.sys.Pod.findType (Pod.java:273)
  compiler::ReflectPod.resolveType (ReflectPod.fan:47)
  compiler::TypeParser.resolve (TypeParser.fan:44)
  compiler::TypeParser.resolve (TypeParser.fan:35)
  compiler::CNamespace.resolveType (CNamespace.fan:227)
  compilerJava::JavaReflect.toFanType (JavaReflect.fan:268)
  compilerJava::JavaReflect.toFanType (JavaReflect.fan)
  compilerJava::JavaReflect.load (JavaReflect.fan:36)
  compilerJava::JavaType.load (JavaType.fan:140)
  compilerJava::JavaType.flags (JavaType.fan:45)
  compiler::CType$.isInternal (Unknown:357)
  compilerJava::JavaType.isInternal (JavaType.fan)
  compiler::Parser.simpleType (Parser.fan:2229)
  fan.sys.List.exclude (List.java:690)
  compiler::Parser.simpleType (Parser.fan:2229)
  compiler::Parser.ctype (Parser.fan:2141)
  compiler::Parser.typeRef (Parser.fan:2095)
  compiler::Parser.typeDef (Parser.fan:227)
  compiler::Parser.parse (Parser.fan:49)
  compiler::Parse.run (Parse.fan:50)
  32 More...

Is there another way to access java code in the fan.sys package?

Also, since Natives are marked as obsolete, what is the recommended strategy for providing an implementation within a single fan source file that can be run on either .net or java?

brian Thu 7 Jan 2010

Unfortunately the way the Fantom classloader works it treats "fan.{foo}" packages as Fantom types, and they can't also be accessed as Java FFI.

Take a look at fanx.interop.Interop - there is a bunch of stuff for switching b/w Java and Fantom IO streams. Maybe there is something we could add to help you out?

Also, since Natives are marked as obsolete, what is the recommended strategy for providing an implementation within a single fan source file that can be run on either .net or java?

I haven't spent a whole lot of time thinking how FFI might replace natives. But now that we have 3 platforms, maybe the native design is the right way. So stick with native as the way to build a cross platform API.

liamstask Thu 7 Jan 2010

Cool - Interop looks like it provides just what I was looking for.

One thing that is not immediately apparent from a quick inspection of the existing code that uses natives is how constructors are handled. For most other methods, a native keyword is applied that seems to indicate that the implementation will be provided by a platform specific source file. (Almost?) none of the constructors seem to use this however, and there seem to be a couple different strategies in use for creating new Fan objects from native code. Any chance you could comment on this or provide a recommended approach?

With the Natives page in the doc declaring them obsolete, there doesn't seem to be much good overview on this. Please let me know if I've missed some!

brian Fri 8 Jan 2010

Sorry native documentation is non-existant, something I sort of neglected b/c I didn't know if that was right long term solution.

Regarding constructors, best to look at fwt and inet example code. You can't really have a native constructor (you can native factory method).

If you don't need subclassing, then I'd suggest a native static factory method.

If you need subclassing, then make a proper Fantom constructor, and hook in during peer creation.

liamstask Fri 8 Jan 2010

Right-o. Thanks again.

Since I'm already subclassing InStream it seems like a native static factory won't work - compiler complains about the :super(null) in the decl. So I'd like to use a normal Fantom constructor, but somewhat surprisingly, I haven't found any examples of passing args to a peer constructor. Perhaps this is not possible and I just need a secondary init step after construction?

I'm not entirely sure what state the Fantom object is in by the time it's passed to the peer, and the ctor args are not being directly set as fields on the Fantom object, so they wouldn't be available that way, even if the object had already been created.

brian Fri 8 Jan 2010

Subclassing InStream with native methods might be tricky. If you are working with Java I/O streams than it might be much safer to wrap raw Java stream with SysInStream and SysOutStream. That is how I did inet.

Login or Signup to reply.