J2ObjC obsługuje osadzanie Objective-C w natywnych metodach Javy, podobnie jak JSNIT w GWT obsługuje umieszczanie JavaScriptu. Główna różnica między umieszczaniem J2ObjC a GWT polega na tym, że J2ObjC używa /*-[
i ]-*/
do wyznaczania kodu Objective-C. Ta usługa nosi nazwę OCNI (Objective-C natywnego interfejsu), aby odróżnić ją od JSNI GWT.
Oto przykład z wersji java.lang.System
biblioteki emulacji JRE:
public static native long currentTimeMillis() /*-[
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
]-*/;
J2ObjC kopiuje komentarz bez ograniczników, aby utworzyć treść metody:
+ (long long int)currentTimeMillis {
// Use NSDate
return (long long) ([[NSDate date] timeIntervalSince1970] * 1000);
}
Importy natywne
J2ObjC skanuje tłumaczony kod Java, aby dodać dyrektyw #import w celu określenia zależności, a także zaimportować platformę Podstawy. Jednak wszystkie importowane dane, które są potrzebne tylko przez kod natywny, musisz dodać osobno. Aby dodać importy, dodaj sekcję OCNI nad pierwszą klasą w pliku źródłowym Java i określ w niej importy, na przykład:
package my.project;
/*-[
#import "java/lang/NullPointerException.h"
]-*/
public class Test {
native void test() /*-[
@throw [[JavaLangNullPointerException alloc] init];
]-*/;
}
W przykładzie powyżej importowanie jest konieczne, ponieważ jedyne miejsce, do którego odwołuje się ten typ, znajduje się w kodzie natywnym.
Blokady natywne
J2ObjC skanuje treść klasy pod kątem bloków OCNI. Bloki te są dodawane do przetłumaczonego pliku bez zmian i w tej samej pozycji względem przekształconych elementów klas. Oto przykład:
/*-[
static void log(NSString *msg) {
NSLog(@"%@", msg);
}
]-*/;
Tę funkcję C można wywołać z dowolnej metody natywnej zadeklarowanej po tym bloku OCNI.
Specjalny wariant tego bloku OCNI wstawia kod w wygenerowanym nagłówku zamiast pliku .m: /*-HEADER[...]
Wywoływanie metod Java z kodu natywnego
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);
]-*/;
Uzyskiwanie dostępu do pól z kodu natywnego
Aby odczytać pole instancji, użyj polecenia myInstanceField_
lub self->myInstanceField_
. Sufiks na końcu pozwala uniknąć konfliktu z metodami o tej samej nazwie.
Pamiętaj, że pola, które mają zarezerwowane nazwy, będą miały 2 znaki podkreślenia. Na przykład pole o nazwie „id” jest dozwolone w języku Java, ale nie w celu C. Po przetłumaczeniu to pole będzie miało nazwę „id__”. Dlatego sprawdź wygenerowane pliki, jeśli występują błędy kompilatora „no-takich pól”.
Aby zapisać w polu instancji obiektu, użyj polecenia JSNIExample_set_myInstanceField(string)
Odczytaj pole statyczne: JSNIExample_get_myStaticField()
Zapisz pole statyczne: JSNIExample_set_myStaticField(value)
J2ObjC i GWT
Zostały wybrane różne separatory, tak aby w następnej wersji J2ObjC komentarze GWT JSNI były ignorowane (wcześniej te same separatory były używane jako GWT). Oznacza to, że pojedyncze źródło w języku Java może zawierać metody natywne z implementacjami Objective-C, GWT i Android (przez JNI):
static native void log(String text) /*-{ // left-brace for JavaScript
console.log(text);
}-*/ /*-[ // left-bracket for Objective-C
NSLog(@"%@", text);
]-*/;
J2ObjC i Android
Implementacje natywnych metod J2ObjC i Androida po prostu działają, ponieważ te metody są implementowane w osobnym pliku JNI C lub C++. Wszelkie komentarze OCNI w klasach Java są usuwane podczas kompilowania przez javac na Androida lub dowolną inną platformę Java.