J2ObjC supporta l'incorporamento di Objective-C nei metodi nativi Java, molto simile a come
JSNI di GWT supporta
incorporamento di JavaScript. La differenza principale tra l'incorporamento di J2ObjC e quello di GWT è che J2ObjC utilizza
/*-[
e ]-*/
per delineare il codice Objective-C. Questa struttura si chiama OCNI (Objective-C
Native Interface), per distinguersi dalla piattaforma JSNI di GWT.
Ecco un esempio tratto dalla versione java.lang.System
della libreria di emulazione JRE:
public static native long currentTimeMillis() /*-[
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
]-*/;
J2ObjC copia il commento, meno i delimitatori, per creare il corpo del metodo:
+ (long long int)currentTimeMillis {
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
}
Importazioni native
J2ObjC analizza anche il codice Java che viene tradotto per aggiungere direttive #import per le sue dipendenze per importare il framework di base. Tuttavia, le eventuali importazioni necessarie solo dal codice nativo aggiunti separatamente. Per aggiungere importazioni, aggiungi una sezione OCNI sopra la prima classe nel file di origine Java e specificare le importazioni; Ad esempio:
package my.project;
/*-[
#import "java/lang/NullPointerException.h"
]-*/
public class Test {
native void test() /*-[
@throw [[JavaLangNullPointerException alloc] init];
]-*/;
}
L'importazione è necessaria nell'esempio precedente perché l'unica posizione a cui viene fatto riferimento al tipo è in il codice nativo.
Blocchi nativi
All'interno di un organismo di classe, J2ObjC cerca i blocchi OCNI. Questi blocchi vengono aggiunti senza essere modificati il file tradotto, nella stessa posizione rispetto ai membri del corso tradotti. Ecco un esempio:
/*-[
static void log(NSString *msg) {
NSLog(@"%@", msg);
}
]-*/;
Questa funzione C può essere richiamata da qualsiasi metodo nativo dichiarato dopo questo blocco OCNI.
Una variante speciale di questo blocco OCNI inserisce il codice nell'intestazione generata
del file .m: /*-HEADER[...]
Richiamo di metodi Java da codice nativo
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);
]-*/;
Accesso ai campi da Native Code
Per leggere un campo di istanza, utilizza myInstanceField_
o
self->myInstanceField_
. Il suffisso finale evita un conflitto con i metodi
con lo stesso nome.
Tieni presente che i campi che hanno nomi riservati contengono due trattini bassi. Ad esempio: un campo denominato "id" è legale in Java, ma non nell'Obiettivo C. Quando viene tradotto, quel campo si chiamerà "id__". Controlla quindi i file generati se ci sono dei "campi assunti" e gli errori del compilatore.
Per scrivere nel campo di un'istanza dell'oggetto, utilizza JSNIExample_set_myInstanceField(string)
Leggi un campo statico: JSNIExample_get_myStaticField()
Scrivi un campo statico: JSNIExample_set_myStaticField(value)
J2ObjC e GWT
Sono stati scelti delimitatori diversi in modo che nella prossima release di J2ObjC, i commenti di GWT JSNI saranno ignorati (in precedenza venivano utilizzati gli stessi delimitatori di GWT). Ciò significa che una singola origine Java può dispongono di metodi nativi con implementazioni Objective-C, GWT e Android (tramite JNI):
static native void log(String text) /*-{ // left-brace for JavaScript
console.log(text);
}-*/ /*-[ // left-bracket for Objective-C
NSLog(@"%@", text);
]-*/;
J2ObjC e Android
Le implementazioni dei metodi nativi Android e J2ObjC "funzionano", perché i metodi nativi Android implementato in un file JNI C o C++ separato. Eventuali commenti OCNI nelle classi Java vengono rimossi quando compilato da javac per Android o qualsiasi altra piattaforma Java.