2013-05-20 3 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) 메서드를 호출하여 프레임의 레이블 my previous question 대답 Roger Rowland

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

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

덕분에 나는 env->CallIntMethod(...?, mid, jstr);이 작동하기 위해서는 개체를 필요가 있음을 알고있다. 그러나 실제로 이미 main(String[] args) 호출에서 생성 된 Sample2 객체의 인스턴스가 있습니다. 따라서 내 주요 질문은 으로 전달하여 C++ 내의 public static void main(String[] args) 양식에서 생성 된 객체에 액세스하여 레이블을 변경하는 방법입니다.

면책 조항 : 나는, 아직도 내가 모든 것을 내가 공공 정적에서 만든 객체에 액세스 할 수있는 방법을 env->CallIntMethod(...?, mid, jstr);

답변

3

까지 의도 한 개미로 작동하는 것을 보장 할 수있는 코드의 길이를 줄이기 위해 검사의 일부를 제거 void main (String [] args)

안되요. 코드에서 인스턴스가 로컬로 선언 된 것은 확실합니다. 당신이 Sample2를 인스턴스화 할 수 main이 정말 그렇게 간단 경우,

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

에 의해 클래스에서 필드 instance를 해결 또는 수

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

를 그 후에 : 당신이 필요로하거나 자바 코드에서 정적 필드를 선언하는 이유입니다 바로 C + + 코드에서 - 심지어 호출하지 않고 main

+0

그게 내가 두려워했던거야 ... 상호 작용하려는 자바 프로그램은 많은 클래스 파일에 흩어져있다 ... 나는 h main 메소드를 호출하여 java 프로그램을 시작한 다음 하위 클래스의 메소드를 호출하여 상호 작용할 수 있습니다. 하지만 JNI가 다른 것을 시도하도록 두려워합니다 ... – Spekkie

+0

' main'은 잘 작동하지만 클래스 인스턴스를 어딘가에 유지하십시오 (정적 필드이면 충분합니다) – Dewfy

+0

그래, 그렇지만 사용하고자하는 전체 Java 프로그램을 다시 작성해야 할 것입니다 ... 그리고 나는 그럴 필요가 없습니다. 많은 시간 ... 여전히 통찰력과 대답을 주셔서 감사합니다 :) – Spekkie

관련 문제