1

What I eventually try to achieve is starting a java program from within C++ and then interact with it using JNI.

So I created a simple testing environment to fool around and to learn more about JNI and how to use it.

This is what I have so far:

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);
            }

now what I'm trying to do next is to change the label of the frame by calling the changeLabel(String s) method.

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

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

Thanks to Roger Rowland who answered my previous question I know that env->CallIntMethod(...?, mid, jstr); needs an object in order to work. But there is actually already an instance of a Sample2 object created in the main(String[] args) call, so my main question is, how can I access the object created in public static void main(String[] args) form within C++ to pass it on to env->CallIntMethod(...?, mid, jstr); in order to change the label.

Disclaimer: I removed some of the checks to reduce the length of the code, still I can assure that everything works as intended up ant until env->CallIntMethod(...?, mid, jstr);

1 Answer 1

3

how can I access the object created in public static void main(String[] args)

No way. From your code you it is clear that instance declared locally. That is why you need either declare static field in java code:

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

After that you can resolve field instance from class by

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

Or, if your main is really so simple you can instantiate Sample2 right from c++ code - even without invoking main

Sign up to request clarification or add additional context in comments.

3 Comments

That's what I was afraid of... The java Program I intend to interact with is scattered over many class files... I was hoping to be able to start the java program by calling the main method and then interact with by calling methods from subclasses... But I'm afraid that I'll have to let JNI go and try something else...
main works good - but keep class instance somewhere (static field is enough)
Yeah, but for that I'll have to rewrite the entire java program I intent to use... And I'm afraid I don't have that much time... Still, thanks for the insight and answer :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.