Écrire des méthodes natives

J2ObjC est compatible avec l'intégration d'Goal-C dans les méthodes natives de Java, de la même manière que JSNI de GWT prend en charge l'intégration JavaScript. La principale différence entre les représentations vectorielles continues J2ObjC et celles de GWT est que J2ObjC utilise /*-[ et ]-*/ pour délimiter le code Objectif-C. Cette fonctionnalité, appelée OCNI (interface native Objectif-C), se distingue de l'interface JSNI de GWT.

Voici un exemple issu de la version java.lang.System de la bibliothèque d'émulation JRE:

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

J2ObjC copie le commentaire, moins les délimiteurs, pour créer le corps de la méthode:

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

Importations natives

J2ObjC analyse le code Java en cours de traduction afin d'ajouter des directives #import pour ses dépendances, ainsi que d'importer le framework Foundation. Toutefois, toutes les importations nécessaires uniquement par le code natif doivent être ajoutées séparément. Pour ajouter des importations, ajoutez une section OCNI au-dessus de la première classe du fichier source Java et spécifiez-y les importations. Par exemple:

  package my.project;

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

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

L'importation est nécessaire dans l'exemple ci-dessus, car le seul endroit auquel ce type est référencé se trouve dans le code natif.

Blocs natifs

Dans un corps de classe, J2ObjC recherche les blocs OCNI. Ces blocs sont ajoutés sans modification au fichier traduit, à la même position par rapport aux membres de la classe traduits. Exemple :

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

Cette fonction C peut être appelée à partir de n'importe quelle méthode native déclarée après ce bloc OCNI.

Une variante spéciale de ce bloc OCNI insère du code dans l'en-tête généré au lieu du fichier .m: /*-HEADER[...]

Appeler des méthodes Java à partir du code natif

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);
]-*/;

Accéder aux champs à partir du code natif

Pour lire un champ d'instance, utilisez myInstanceField_ ou self->myInstanceField_. Le suffixe de fin évite un conflit avec des méthodes portant le même nom.

Notez que les champs qui ont des noms réservés auront deux traits de soulignement. Par exemple, un champ nommé "id" est légal en Java, mais pas dans l'objectif C. Une fois traduit, ce champ sera nommé "id__". Par conséquent, veuillez vérifier les fichiers générés s'il existe des erreurs de compilateur "no-such-field".

Pour écrire dans un champ d'instance d'objet, utilisez JSNIExample_set_myInstanceField(string).

Lire un champ statique: JSNIExample_get_myStaticField()

Écrire un champ statique: JSNIExample_set_myStaticField(value)

J2ObjC et GWT

Différents délimiteurs ont été choisis afin que dans la prochaine version de J2ObjC, les commentaires JSNI de GWT soient ignorés (auparavant, les mêmes délimiteurs étaient utilisés pour GWT). Cela signifie qu'une seule source Java peut comporter des méthodes natives ayant des implémentations Goal-C, GWT et Android (via JNI) :

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

J2ObjC et Android

Les implémentations de méthodes natives J2ObjC et Android "fonctionnent", car les méthodes natives Android sont implémentées dans un fichier JNI C ou C++ distinct. Tous les commentaires OCNI dans les classes Java sont supprimés lorsqu'ils sont compilés par javac pour Android ou toute autre plate-forme Java.