Native Methoden schreiben

J2ObjC unterstützt das Einbetten von Objective-C in native Java-Methoden, ähnlich wie das JSNI von GWT die JavaScript-Einbettung unterstützt. Der Hauptunterschied zwischen J2ObjC-Einbettungen und GWTs besteht darin, dass J2ObjC /*-[ und ]-*/ verwendet, um Objective-C-Code abzugrenzen. Diese Einrichtung wird als OCNI (Objective-C Native Interface) bezeichnet, um sich vom JSNI von GWT zu unterscheiden.

Hier ein Beispiel aus der Version von java.lang.System der JRE-Emulationsbibliothek:

  public static native long currentTimeMillis() /*-[
    // Use NSDate
    return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
  ]-*/;

J2ObjC kopiert den Kommentar ohne Trennzeichen, um den Methodentext zu erstellen:

  + (long long int)currentTimeMillis {
    // Use NSDate
    return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
  }

Native Importe

J2ObjC scannt den zu übersetzenden Java-Code, um #import-Anweisungen für seine Abhängigkeiten hinzuzufügen und das Foundation-Framework zu importieren. Importe, die nur von nativem Code benötigt werden, müssen jedoch separat hinzugefügt werden. Fügen Sie zum Hinzufügen von Importen einen OCNI-Abschnitt über der ersten Klasse in der Java-Quelldatei hinzu und geben Sie die Importe dort an. Beispiel:

  package my.project;

  /*-[
  #import "java/lang/NullPointerException.h"
  ]-*/

  public class Test {
    native void test() /*-[
      @throw [[JavaLangNullPointerException alloc] init];
    ]-*/;
  }

Der Import ist im obigen Beispiel erforderlich, da auf diesen Typ nur im nativen Code verwiesen wird.

Native Blockierungen

Innerhalb eines Klassenkörpers sucht J2ObjC nach OCNI-Blöcken. Diese Blöcke werden der übersetzten Datei unverändert hinzugefügt, und zwar an derselben Position, bezogen auf die übersetzten Klassenmitglieder. Beispiel:

  /*-[
    static void log(NSString *msg) {
      NSLog(@"%@", msg);
    }
  ]-*/;

Diese C-Funktion kann von jeder nativen Methode aufgerufen werden, die nach diesem OCNI-Block deklariert wird.

Eine spezielle Variante dieses OCNI-Blocks fügt Code in den generierten Header anstelle der .m-Datei ein: /*-HEADER[...]

Java-Methoden aus nativem Code aufrufen

public native void bar(JSNIExample x, String s) /*-[
  // Call instance method instanceFoo() on this
  [self instanceFooWithNSString:s];

  // Call instance method instanceFoo() on x
  [x instanceFooWithNSString:s];

  // Call static method staticFoo()
  JSNIExample_staticFooWithNSString_(s);
]-*/;

Über nativen Code auf Felder zugreifen

Verwenden Sie zum Lesen eines Instanzfelds entweder myInstanceField_ oder self->myInstanceField_. Das nachgestellte Suffix vermeidet einen Konflikt mit Methoden, die denselben Namen haben.

Beachten Sie, dass Felder mit reservierten Namen zwei Unterstriche enthalten. Ein Feld namens „id“ ist beispielsweise in Java zulässig, in Objective C jedoch nicht. Nach der Übersetzung erhält dieses Feld den Namen „id__“. Prüfen Sie daher die generierten Dateien auf Compiler-Fehler vom Typ „no-such-field“.

Verwenden Sie JSNIExample_set_myInstanceField(string), um in ein Objektinstanzfeld zu schreiben

Statisches Feld lesen: JSNIExample_get_myStaticField()

Statisches Feld schreiben: JSNIExample_set_myStaticField(value)

J2ObjC und GWT

Es wurden andere Trennzeichen ausgewählt, damit im nächsten J2ObjC-Release GWT JSNI-Kommentare ignoriert werden (zuvor wurden dieselben Trennzeichen wie in GWT verwendet). Dies bedeutet, dass eine einzelne Java-Quelle native Methoden mit Objective-C-, GWT- und Android-Implementierungen (über JNI) enthalten kann:

  static native void log(String text) /*-{ // left-brace for JavaScript
    console.log(text);
  }-*/ /*-[                                // left-bracket for Objective-C
     NSLog(@"%@", text);
  ]-*/;

J2ObjC und Android

Native J2ObjC- und Android-Methodenimplementierungen „funktionieren einfach“, da native Android-Methoden in einer separaten JNI C- oder C++-Datei implementiert werden. Alle OCNI-Kommentare in Java-Klassen werden entfernt, wenn sie von javac für Android oder einer anderen Java-Plattform kompiliert werden.