1

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

所以我创建了一个简单的测试环境来玩转并学习更多关于 JNI 以及如何使用它的知识。

这是我到目前为止所拥有的:

示例2.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回答了我之前的问题,我知道env->CallIntMethod(...?, mid, jstr);需要一个对象才能工作。但实际上已经在main(String[] args)调用中创建了一个 Sample2 对象的实例,所以我的主要问题是,如何访问public static void main(String[] args)在 C++ 中以表单创建的对象以将其传递给以env->CallIntMethod(...?, mid, jstr);更改标签。

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

4

1 回答 1

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真的很简单,你可以Sample2直接从 c++ 代码实例化——即使不调用main

于 2013-05-20T10:06:36.243 回答