Menulis Metode Native

J2ObjC mendukung penyematan Objective-C ke dalam metode native Java, sangat mirip dengan cara JSNI GWT mendukung penyematan JavaScript. Perbedaan utama antara penyematan J2ObjC dan GWT adalah J2ObjC menggunakan /*-[ dan ]-*/ untuk menandai kode Objective-C. Fasilitas ini disebut OCNI (Objective-C Native Interface), untuk membedakan diri dari JSNI GWT.

Berikut ini contoh dari java.lang.System versi library emulasi JRE:

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

J2ObjC menyalin komentar, tanpa pemisah, untuk membuat isi metode:

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

Impor Native

J2ObjC memindai kode Java yang diterjemahkan guna menambahkan perintah #import untuk dependensinya, serta mengimpor framework Foundation. Namun, semua impor yang hanya diperlukan oleh kode native perlu ditambahkan secara terpisah. Untuk menambahkan impor, tambahkan bagian OCNI di atas class pertama dalam file sumber Java dan tentukan impor di sana; misalnya:

  package my.project;

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

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

Impor diperlukan dalam contoh di atas karena satu-satunya tempat jenis tersebut yang dirujuk adalah dalam kode native.

Pemblokiran Native

Dalam isi class, J2ObjC memindai blok OCNI. Blok ini ditambahkan tanpa dimodifikasi ke file terjemahan, di posisi yang sama relatif terhadap anggota class yang diterjemahkan. Berikut contohnya:

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

Fungsi C ini dapat dipanggil dari metode native apa pun yang dideklarasikan setelah blok OCNI ini.

Varian khusus dari blok OCNI ini menyisipkan kode dalam header yang dihasilkan, bukan file .m: /*-HEADER[...]

Memanggil Metode Java dari Kode Native

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

Mengakses kolom dari Kode Native

Untuk membaca kolom instance, gunakan myInstanceField_ atau self->myInstanceField_. Akhiran di akhir akan menghindari bentrok dengan metode yang memiliki nama yang sama.

Perhatikan bahwa kolom yang memiliki nama yang dicadangkan akan memiliki dua garis bawah. Misalnya, kolom bernama "id" legal di Java, tetapi tidak di Objective C. Saat diterjemahkan, kolom tersebut akan diberi nama "id__". Oleh karena itu, periksa file yang dibuat jika ada error compiler "no-such-field".

Untuk menulis ke kolom instance objek, gunakan JSNIExample_set_myInstanceField(string)

Membaca kolom statis: JSNIExample_get_myStaticField()

Tulis kolom statis: JSNIExample_set_myStaticField(value)

J2ObjC dan GWT

Pembatas yang berbeda dipilih sehingga pada rilis J2ObjC berikutnya, komentar GWT JSNI akan diabaikan (sebelumnya pemisah yang sama digunakan sebagai GWT). Ini berarti bahwa satu sumber Java dapat memiliki metode native yang memiliki implementasi Objective-C, GWT, dan Android (melalui JNI):

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

J2ObjC dan Android

Implementasi metode native Android dan J2ObjC "langsung berfungsi", karena metode native Android diimplementasikan dalam file JNI C atau C++ yang terpisah. Semua komentar OCNI di class Java akan dihapus saat dikompilasi oleh javac untuk Android atau platform Java lainnya.