Pisanie metod natywnych

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.