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 によってコンパイルされると削除されます。