2012-05-14 41 views
2

我有一個調用我的C++代碼的本機函數調用,此代碼創建了我的用戶定義類的實例。Android NDK/General JNI問題:將對象/ jobject轉換爲C++用戶defiend類型

該功能具有以下特徵:這已經調用

public native Object loadEngine(int arg); 

後,我想調用,將採取「對象」從loadEngine()返回,並修改它更多的原生功能,或從中請求數據。

簽名的例子:

public native String loadEngine(Object engine, int queryID); 
  1. 它甚至有可能做到這一點?
  2. 如果可能的話,我會如何將我的GameEngine數據類型轉換爲java對象或jni jobject。
  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代碼,我unfortunatily不能定義本地函數爲:

public native GameEngine loadEngine(int arg); 

可以理解,但我似乎無法能夠找出一個解決辦法。

謝謝,猩紅。

回答

4

您可以創建包含,擁有和管理您的本機代碼的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代表本地指針。這就是Java運行時在需要時如何執行(例如,在java.niojava.util.zip程序包中。)long而不是int可確保該類型足夠寬以在64位系統上保留指針。

+1

這是非常有趣的罰款先生。這是否意味着要從「外部」調用某些C++成員函數,他們實際上必須被包裝起來?那麼Object的用途是什麼? – ScarletAmaranth

+0

'Object'和'jobject'指的是Java對象。 Java對C++,C++類或C++類型系統沒有直接的瞭解。還有其他的方法可以在Java中使用C++類,但是這個方法可以讓你用C++編寫你的邏輯,並且在平臺特定語言(Java)中只有一個很小的包裝器。這意味着你可以重複使用完全相同的邏輯代碼在諸如iOS,Windows,Mac OS X,Linux等其他平臺上,Java可能可用也可能不可用。 –

相關問題