2011-02-11 65 views
2

我真的很想弄清楚如何使用JNI從Objective-C調用Java函數。從可可與JNI調用Java類函數

我應該首先說我對Java沒什麼瞭解,但對於Obj-C非常熟悉。我有一個單獨的Java類,需要從我的應用程序包中調用。該jar包位於資源文件夾中,我有NSJavaRoot設置爲Content/Resources,NSJavaNeeded被選中,NSJavaPath包含2個jar文件(主要的一個和一個依賴項)的名稱。

我打電話給JNI_CreateJavaVM,然後試圖找到使用NSClassFromString這個類感覺錯了,但是我在我的搜索中找到的唯一方法。我相信這種方法在使用棄用的Java橋時是正確的,但我找不到任何使用JNI的示例或引用。

我的Java類看起來是這樣的:

package foo; 

public class bar { 

    public function dostuff() { 

    } 

} 

我需要調用一次dostuff()作爲應用流程的一部分。有沒有人有任何想法如何做到這一點?

感謝, Ĵ

回答

12

因爲JavaBridge的已被棄用,你將不得不做這一切與JNI。在MacOS上,你要的JavaVM.framework添加到您的項目,並從您的源文件,你要找的標題是:

#import <JavaVM/jni.h> 

接下來,您需要設置在JavaVM。這可能是不平凡的,這取決於你的classpath和其他要求,但你在正確的軌道上,因爲這是你函數用於創建JVM:

JNI_CreateJavaVM(JavaVM **pJVM, void **pJNIEnv, void *args); 

下一步,你想獲得一個引用你的類foo.bar。這可以使用從JNI_CreateJavaVM傳出的pJNIEnv來完成。你需要撥打:

jclass myClass = JNIEnv->FindClass(JNIEnv, "foo/bar"); // Note the slashes replacing the dots... 

假設一切都設置正確,你會得到一個對你的課程的參考。假設該foo.bar具有默認參數的構造函數的那一刻,你可以得到一個實例,就像這樣:

jobject myFooBar = JNIEnv->NewObject(JNIEnv, myClass); 

現在,你需要得到您的doStuff方法放在methodID。要做到這一點,你需要它的方法簽名,你可以通過調用javap的獲得,是這樣的:

% javap -s foo.bar 

應該產生這樣的輸出:

Compiled from "bar.java" 
public class foo.bar extends java.lang.Object{ 
public foo.bar(); 
    Signature:()V 
public void doStuff(); 
    Signature:()V 
} 

然後,你可以用它來獲取您需要調用它的methodID。像這樣:

jmethodID mid = JNIEnv->GetMethodID(JNIEnv, myClass, "doStuff", "()V"); 

假設所有這些事情都過去了吧,然後就可以調用的方法是這樣的:

JNIEnv->CallVoidMethod(JNIEnv, myFooBar, mid); 

和方法應被調用。在任何這些階段之後,您可能需要檢查虛擬機以查看是否有異常。您可以檢查,看是否發生了由這樣一個例外:

if (JNIEnv->ExceptionCheck(JNIEnv)) 
{ 
    // Handle the exception... 
} 

如果你想實際拋出,則可以使用ExceptionOccurred JNI方法得到它。

所以,在它最精簡的地方:如何從JNI調用Cocoa的Java方法。您需要閱讀JNI文檔,尤其是瞭解全球和本地參考文獻之間差異的部分。 (即讓你的可可邊參照持續足夠長的時間,以便在它們被創建的範圍之外被調用)。實際上,關於常見的錯誤和陷阱有很多章節,其中很多會碰到它們。

http://java.sun.com/docs/books/jni/

祝你好運!

+0

謝謝,這正是我通過反覆試驗完成的。希望這個非常明確的描述能夠幫助那些被困在相同情況下的人! – JWood 2011-04-13 13:37:33