Interfacing with native Java code: Creating externs

One of the main design principles of the Java target was to make it 100% interoperable with native Java code. This means that from Haxe code you should be able to use external libraries, share your own common code, and even extend native code without the need of "glue code".

This was made simpler with some equivalence of Java basic types and Haxe basic types:

in Java, the following class definition:

public class Test
{
    public static void someTest(String a, int b, boolean c)
    {
    }
}

could be reused from inside Haxe code with the following extern definition:

extern class Test
{
    public static function someTest(a:String, b:Int, c:Bool):Void;
}

You can later use the "someTest" function in your own code like this:

Test.someTest("a string", 10, true);
Extern definitions are a way for Haxe to interoperate with native code. They provide the definitions so Haxe can type-check them, but without the need to provide the actual implementations, which are expected to be implemented in native code.

Type Equivalences

  • Java Object => Haxe Dynamic (no need to import any module)
  • Java String => Haxe String (no need to import any module)
  • Java int => Haxe Int (no need to import any module)
  • Java double => Haxe Float (no need to import any module)
  • Java float => Haxe Single (no need to import any module)
  • Java boolean => Haxe Bool (no need to import any module)
  • Java void => Haxe Void (no need to import any module)
  • Java byte => Haxe Int8 import java.StdTypes;
  • Java short => Haxe Int16 import java.StdTypes;
  • Java char => Haxe Char16 import java.StdTypes;
  • Java long => Haxe Int64 import haxe.Int64;
  • Java arrays => see below

Java Native Arrays

You can also use Java Native Arrays from within Haxe. You need to define them with the type java.NativeArray<>:

The following Java code:

int[] aint = new int[10];
string[][] aastr = new string[10][];

aint[1] = 1;
aastr[0] = new string[10];
aastr[0][0] = "Hello";

System.out.println(aint[1]); //1
System.out.println(aastr[0][0]); //Hello

can be translated into the following Haxe code:

var aint = new NativeArray<Int>(10);
var aastr = new NativeArray<NativeArray<String>>(10);

aint[1] = 1;
aastr[0] = new NativeArray(10);
aastr[0][0] = "Hello";

trace(aint[1]); //1
trace(aastr[0][0]); //Hello

Note that the code above is overly verbose for clarity. We could as well have done the following:

var aint = new NativeArray(10);
var aastr = new NativeArray(10);

and let the type inference do its job!

Iterating over Java Native Arrays


As of version 2.10, item iteration is not supported for Java native arrays. Instead, the following construct should be used:
var iarray:NativeArray<Int> = new NativeArray(10);
for (i in 0...iarray.length)
{
    iarray[i] = i;
}

Overloading

Haxe does not support method overloading definition. But to interoperate better with native code, the @:overload metada can be used.

Please take care when using overload for their order of definition. The current overload resolution algorithm in Haxe will take the first function definition which fits the function arguments.

For example in the following definitions:

@:overload(function(a:Int):Void{})
@:overload(function(a:String):Void{})
function test(a:Dynamic):Void;

@:overload(function(a:Dynamic):Void{})
@:overload(function(a:String):Void{})
function test2(a:Int):Void;

the following calls:

myInstance.test("string");
myInstance.test2("string");

will both call test2 as if its arguments were Dynamics. This is because Haxe will first evaluate the original function definition (the named function), and later will check each @:overload in the order they were declared.
A better version of these definitions would then be:

@:overload(function(a:String):Void{})
@:overload(function(a:Dynamic):Void{})
function test(a:Int):Void;

@:overload(function(a:Int):Void{})
@:overload(function(a:Dynamic):Void{})
function test2(a:String):Void;

Note that the least specific type ("Dynamic") is the last to be called

Type Parameters


Type parameters can be declared just like they are declared in Haxe.

Automatic Generation of Externs


Because of the great similarities between Haxe type system and Java, automatic externs generation can be achieved. You can refer to the Haxe Java Extern project and Java Extern Creator. It is planned to add all the Java Standard library definitions to the official distribution of Haxe before Haxe 3.0, while they are tested before being included.
Also there are plans to add direct .jar / .class input support for Haxe, without the need of generating externs.
version #15265, modified 2012-08-04 17:51:20 by jan_flanders