ネイティブ メソッドの記述

J2ObjC は、GWT の JSNI が JavaScript の埋め込みをサポートするのとよく似ています。J2ObjC 埋め込みと GWT の主な違いは、J2ObjC では /*-[]-*/ を使用して Objective-C コードを記述していることです。この機能は OCNI(Objective-C ネイティブ インターフェース)と呼ばれ、GWT の JSNI と区別されます。

JRE エミュレーション ライブラリのバージョン java.lang.System の例を次に示します。

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

J2ObjC は、コメントから区切り文字を除いたものをコピーしてメソッド本体を作成します。

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

ネイティブ インポート

J2ObjC は、変換される Java コードをスキャンし、依存関係の #import ディレクティブを追加し、Foundation フレームワークをインポートします。ただし、ネイティブ コードでのみ必要なインポートは別途追加する必要があります。インポートを追加するには、Java ソースファイルの最初のクラスの上に OCNI セクションを追加し、そこでインポートを指定します。次に例を示します。

  package my.project;

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

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

上記の例では、ネイティブ コード内に型が参照されているため、インポートが必要です。

ネイティブ ブロック

クラス本体内で、J2ObjC は OCNI ブロックをスキャンします。これらのブロックは、変更されることなく翻訳ファイルに追加されます。これは、翻訳後のクラスメンバーに対する相対位置と同じ位置に配置されます。次の例をご覧ください。

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

この C 関数は、この OCNI ブロックの後に宣言されたネイティブ メソッドから呼び出すことができます。

この OCNI ブロックの特別なバリアントでは、.m ファイルではなく生成されたヘッダーにコード /*-HEADER[...] が挿入されます。

ネイティブ コードから Java メソッドの呼び出し

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

ネイティブ コードからフィールドにアクセスする

インスタンス フィールドを読み取るには、myInstanceField_ または self->myInstanceField_ を使用します。末尾のサフィックスを使用すると、同じ名前のメソッドとの競合を回避できます。

予約済みの名前を持つフィールドには 2 つのアンダースコアが表示されます。たとえば、「id」という名前のフィールドは Java では有効ですが、Objective C では有効ではありません。翻訳されると、そのフィールドは「id__」という名前になります。そのため、「no-such-field」コンパイラ エラーが発生している場合は、生成されたファイルを確認してください。

オブジェクト インスタンス フィールドに書き込むには、JSNIExample_set_myInstanceField(string) を使用します。

静的フィールド JSNIExample_get_myStaticField() の読み取り

静的フィールド JSNIExample_set_myStaticField(value) を記述します。

J2ObjC と GWT

次の J2ObjC リリースで GWT JSNI コメントが無視されるように、異なる区切り文字が選択されました(以前は GWT と同じ区切り文字が使用されていました)。つまり、1 つの Java ソースが、Objective-C、GWT、Android(JNI 経由)の実装を持つネイティブ メソッドを持つことができます。

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

J2ObjC と Android

Android ネイティブ メソッドは、個別の JNI C または C++ ファイルで実装されているため、J2ObjC と Android のネイティブ メソッドの実装は「そのまま機能する」ためです。Java クラス内の OCNI コメントは、Android 用やその他の Java プラットフォーム用の javac によってコンパイルされると削除されます。