2013-05-20 54 views
1

我最終試圖實現的是從C++中啓動一個java程序,然後使用JNI與它進行交互。在C++的java代碼中創建的訪問對象

因此,我創建了一個簡單的測試環境,以便學習更多關於JNI以及如何使用它的知識。

這是我到目前爲止有:

Sample2.java:

public class Sample2 { 

    JLabel testLabel; 

    public static boolean booleanMethod(boolean bool) { 
     return !bool; 
    } 

    public Sample2(){ 
     JFrame frame = new JFrame("FrameDemo"); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     testLabel = new JLabel("test"); 
     testLabel.setPreferredSize(new Dimension(175, 100)); 
     frame.getContentPane().add(testLabel, BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     new Sample2(); 
    } 

    public void changeLabel(String s){ 
     testLabel.setText(s); 
    } 
} 

JNITest.cpp:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    JavaVMOption options[3]; 
    static JNIEnv *env; 
    JavaVM *jvm; 
    JavaVMInitArgs vm_args; 
    long status; 
    jclass cls, stringClass; 
    jmethodID mid; 
    jstring jstr; 
    jobjectArray args; 
    jobject obj; 

    options[0].optionString = "-Djava.class.path=D:\\Studie\\EXP\\Code\\Workspace\\JNItest\\bin"; //2APL\\build"; //Workspace\\JNItest\\bin"; 
    options[1].optionString = "-verbose"; 
    options[2].optionString = "-verbose:jni"; 
    memset(&vm_args, 0, sizeof(vm_args)); 
    vm_args.version = JNI_VERSION_1_6; 
    vm_args.nOptions = 1; 
    vm_args.options = options; 
    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 

    if (status != JNI_ERR) { 
     cls = env->FindClass("Sample2"); 
     if(cls !=0) { 
      mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V"); 
      if(mid !=0) { 
       jstr = env->NewStringUTF("-nojade"); 
       stringClass = env->FindClass("java/lang/String"); 
       args = env->NewObjectArray(1, stringClass, jstr); 
       env->CallStaticVoidMethod(cls, mid, args); 
      } 

現在我嘗試下一步要做的是改變該框架的標籤通過調用changeLabel(String s)方法。

  mid = env->GetMethodID(cls, "changeLabel", "(Ljava/lang/String;)V"); 
      jstr = env->NewStringUTF("foobar"); 
      env->CallIntMethod(...?, mid, jstr); 

     } 
     jvm->DestroyJavaVM(); 
     return 0; 
    } 
    else { 
     return -1; 
    } 
} 

感謝Roger Rowland誰回答my previous question我知道env->CallIntMethod(...?, mid, jstr);需要爲了工作的對象。但實際上已經有一個在main(String[] args)調用中創建的Sample2對象的實例,所以我的主要問題是,如何訪問在C++中的public static void main(String[] args)窗體中創建的對象以將其傳遞到env->CallIntMethod(...?, mid, jstr);以更改標籤。

免責聲明: 我刪除了一些檢查,以減少代碼的長度,還是我可以保證,一切都會按計劃了螞蟻,直到env->CallIntMethod(...?, mid, jstr);

回答

3

我如何可以訪問公共靜態創建的對象void main(String [] args)

沒辦法。從你的代碼你很清楚,實例在本地聲明。這就是爲什麼你需要或者在Java代碼中聲明靜態字段:

static Sample2 instance; 
public static void main(String[] args) { 
    instance = new Sample2(); 
} 

之後,你可以從類的

fid = (*env)->GetStaticFieldID(
    env, cls, "instance", "LSample2;"); 

解決現場instance或者,如果您main是真的這麼簡單,你可以實例Sample2正確的C++代碼 - 即使沒有調用main

+0

這就是我害怕的...... 我打算與之交互的java程序分散在許多類文件中......我是h選擇能夠通過調用main方法來啓動java程序,然後通過調用子類的方法進行交互... 但是,我恐怕必須讓JNI去嘗試其他方法... – Spekkie

+0

'主'工作良好 - 但保持在某個地方的類實例(靜態字段已經足夠) – Dewfy

+0

是的,但爲此,我將不得不重寫整個Java程序,我打算使用...而我恐怕我沒有很多時間... 仍然,感謝您的洞察力和答案:) – Spekkie