2009-11-10 78 views
12

我目前在一個項目中同時使用C++和Java,我希望能夠發送一個包含在C++中的對象到我的Java接口,以便通過它來修改它一個GUI,然後用C++發回修改。通過JNI返回一個C++類到Java

到目前爲止,我一直通過JNI接口向Java返回int或boolean。這一次我必須通過界面發送一個對象。我已經在C++和Java中提供了類似的類定義。 我想知道如何創建對象,以便我可以在Java中使用它。

在C++中,我有:

JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number); 

此功能將被Java,以獲得從C++側對象被調用(的對象包含在一個單,方便)。

在Java年底,我做一個簡單的調用這個方法,

MyObject anObject = C_getMyObject(3); 

應該還給我新創建的對象。

當我執行實際調用時,Java當前返回一個UnsatisfiedLinkError。哪裏不對?

回答

10

這是我選擇使用的解決方案:

首先,我會在Java中創建一個類似的對象。然後,從C++中,我會instanciate並傳遞所有的值。

(C++) 
clazz = env->FindClass("java/lang/Integer"); 
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V"); 
return env->NewObject(clazz, method, (jint)anInteger); 

但後來我意識到這不是很便攜,有點太複雜。

取而代之,我決定返回一個Java解析並用於初始化對象的字符串。

(JAVA) 
String aString = "valuesoftheobject"; 
MyObject myObject(aString); 

MyObject將有一個接受字符串的構造函數。我相信這個解決方案簡單而有效。

4

如果您的MyObject類是用C++定義的,那麼您將無法使用Java訪問其方法。我想嘗試限定圍繞你的C對象的Java包裝類:

Java: 
public C_Object() { 
    handle = createHandle(); 
} 

private native long createHandle(); // or whatever pointer/handle type? 

public void doStuff() { 
    _doStuff(handle); 
} 

private native void _doStuff(long handle); 

如果可以推斷一個C API,而不是,你可以嘗試JNA

Your UnsatisfiedLinkError可能是上面寫的函數名中的額外字符,或者它可能無法處理返回值MyObject

4

你應該看看的另一個工具是SWIG。 SWIG是用於爲其他語言(例如Java,Python或C#)生成用於現有C/C++對象的封裝器的好工具。它將圍繞C/C++對象生成自動的Java包裝,併爲您完成所有繁重的JNI工作。

我在Xuggler中廣泛使用它。要看到一個例子,如果你下載的Xuggler源代碼中有一個C++對象的位置:

csrc/com/xuggle/xuggler/IStreamCoder.h 

我定義在這裏痛飲接口文件:

csrc/com/xuggle/xuggler/IStreamCoder.i 

當通過痛飲運行它生成一個Java對象(存儲在這裏)

generate/java/com/xuggle/xuggler/IStreamCoder.java 

然後,我們可以訪問從Java該對象容易(當然,我添加一些裁判計數的東西,但是那是相當先進)。希望有所幫助。

藝術