3

c ++コードを呼び出すネイティブ関数呼び出しがあり、このコードはユーザー定義クラスのインスタンスを作成します。

この関数には次のシグネチャがあります。

public native Object loadEngine(int arg);

この呼び出しが行われた後、loadEngine()から返された「オブジェクト」を取得して変更する、またはデータを要求するネイティブ関数をさらに呼び出したいと思います。

署名の例:

public native String loadEngine(Object engine, int queryID);
  1. これを行うことさえ可能ですか?
  2. 可能であれば、GameEngineデータ型をjavaObjectまたはjnijobjectに変換するにはどうすればよいですか。
  3. Javaはこれを参照として自動的に渡すので、コピーされることはなく、変更することもできますよね?

次のシナリオでは、GameEngineを理解できるjobjectに変換できないというエラーが生成されますが、これはJavaの経験がほとんどない私のベストショットです。

JNIEXPORT jobject JNICALL Java_package_loadEngine
  (JNIEnv *env, jobject obj, jint arg) {
     GameEngine engine(params);
     return (jobject)engine;
  }

JNIEXPORT jstring JNICALL Java_package_queryAction
  (JNIEnv *env, jobject obj, jobject engine, jint arg) {
     String ret = newString(Integer.toString((GameEngine)engine.unimportant()));
     return ret;
  }

jniを介してc++にネイティブJavaコードを呼び出しているため、残念ながらネイティブ関数を次のように定義することはできません。

 public native GameEngine loadEngine(int arg);

理解できますが、回避策を理解できないようです。

ありがとう、スカーレット。

4

1 に答える 1

5

ネイティブ コードを含み、所有し、管理する Java ラッパー クラスを作成できます。たとえば(頭のてっぺんから、頭脳でコンパイルされた):

class GameEngine {
    private long nativeGameEnginePointer;

    private native long loadEngine();
    public GameEngine() {
        super(...);
        nativeGameEnginePointer = loadEngine();
    }

    private native void destroyEngine(long nativePointer);
    protected void finalize() throws Throwable {
        try {
            destroyEngine(nativeGameEnginePointer);
        } finally {
            super.finalize();
        }
    }

    private native double nativePlayGameOrWhatever(long nativePointer);
    public double playGameOrWhatever() {
        return nativePlayGameOrWhatever(nativeGameEnginePointer);
    }
}

そして、あなたの JNI 実装では:

class CxxGameEngine;

JNIEXPORT jlong JNICALL GameEngine_loadEngine(JNIEnv *env, jobject obj) {
     return (jlong)(new CxxGameEngine(params));
}

JNIEXPORT jvoid JNICALL GameEngine_destroyEngine(JNIEnv *env, jobject obj, jlong nativePointer) {
     delete (CxxGameEngine *)nativePointer;
}

JNIEXPORT jdouble JNICALL GameEngine_nativePlayGameOrWhatever(JNIEnv *env, jobject obj, jlong nativePointer) {
     return ((CxxGameEngine *)nativePointer)->playGameOrWhatever();
}

longネイティブ ポインターを表すために を使用していることに注意してください。これは、64 ビット システムでもポインターを保持するのに十分な型の幅を保証するのではなく、必要に応じて (たとえば、java.nioおよびjava.util.zipパッケージで) Java ランタイムが実行する方法です。longint

于 2012-05-14T17:55:40.627 に答える