从C ++编写的java代码中创建的访问对象

时间:2013-05-20 09:52:32

标签: java c++ java-native-interface

我最终尝试实现的是从C ++中启动一个java程序,然后使用JNI与它进行交互。

因此,我创建了一个简单的测试环境,以便了解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)形式创建的对象以将其传递给{{ 1}}以便更改标签。

声明: 我删除了一些检查以减少代码的长度,但我可以保证一切都按预期工作,直到env->CallIntMethod(...?, mid, jstr);

1 个答案:

答案 0 :(得分:3)

  

如何访问在public static void main(String [] args)

中创建的对象

没办法。从您的代码中可以清楚地看到本地声明的实例。这就是为什么你需要在java代码中声明静态字段:

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

之后,您可以通过

从课程中解析字段instance
fid = (*env)->GetStaticFieldID(
   env, cls, "instance", "LSample2;");

或者,如果您的main非常简单,您可以直接从c ++代码实例化Sample2 - 即使不调用main