C++ Utiliser objc_msgSend() avec un autre thread que le principale.

oimy

Membre confirmé
29 Mai 2018
14
0
43
Bonjour,

Mon but est d'ouvrir une fenêtre JNI dans un programme existant. Pour cela j'utilise Cocoa sur Mac. Mon programme C++ ainsi que mes classes java fonctionnent très bien hors du programme global.

Mon soucis est que j'obtiens l'erreur suivante "nextEventMatchingMask should only be called from the Main Thread!" sur la ligne utilisant la fonction objc_msgSend() quand j'insère l'appelle la création de la fenêtre dans le programme global.

voici mon code d'appelle à la fenêtre (la partie du main() est inséré dans une fonction du programme global) :
Bloc de code:
#include <iostream>
#include <jni.h>
#include <objc/objc-runtime.h>
void runCocoaMain(void)
{
    id clazz = (id) objc_getClass("NSApplication");
    id _Nullable app = objc_msgSend(clazz, sel_registerName("sharedApplication"));
    objc_msgSend(app, sel_registerName("run"));
}
int main()
{
    using namespace std;
    cout<<"arret ..."<<endl;
    int i;
    cin >> i;
    JavaVM *jvm;                // Pointer to the JVM (Java Virtual Machine)
    JNIEnv *env;                // Pointer to native interface
    //==================== prepare loading of Java VM ============================
    JavaVMInitArgs vm_args;                        // Initialization arguments
    JavaVMOption* options = new JavaVMOption[1];   // JVM invocation options
    options[0].optionString = "-Djava.class.path=.";   // where to find java .class
    vm_args.version = JNI_VERSION_1_8;             // minimum Java version
    vm_args.nOptions = 1;                          // number of options
    vm_args.options = options;
    vm_args.ignoreUnrecognized = JNI_TRUE;     // invalid options make the JVM init fail
    //================= load and initialize Java VM and JNI interface ===============
    jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  // YES !!
    delete options;    // we then no longer need the initialisation options.
    //========================= analyse errors if any  ==============================
    // if process interuped before error is returned, it's because jvm.dll can't be
    // found, i.e.  its directory is not in the PATH.
if (rc == JNI_ERR) {
    printf("All done, bye bye!\n");
}
    if(rc != JNI_OK) {
        if(rc == JNI_EVERSION)
            cerr << "FATAL ERROR: JVM is oudated and doesn't meet requirements" << endl;
        else if(rc == JNI_ENOMEM)
            cerr << "FATAL ERROR: not enough memory for JVM" << endl;
        else if(rc == JNI_EINVAL)
            cerr << "FATAL ERROR: invalid ragument for launching JVM" << endl;
        else if(rc == JNI_EEXIST)
            cerr << "FATAL ERROR: the process can only launch one JVM an not more" << endl;
        else
            cerr << "FATAL ERROR:  could not create the JVM instance (error code " << rc << ")" << endl;
        cin.get();
        exit(EXIT_FAILURE);
    }
    cout << "JVM load succeeded. \nVersion ";
    jint ver = env->GetVersion();
    cout << ((ver >> 16) & 0x0f) << "." << (ver & 0x0f) << endl;
    // First call to JAVA ==================================================================
    jclass cls2 = env->FindClass("MyTest2");  // try to find the class
    if(cls2 == nullptr) {
        cerr << "ERROR: class not found !";
    }
    else {                                  // if class found, continue
        cout << "Class MyTest found" << endl;
             //       runCocoaMain();
        jmethodID mid = env->GetStaticMethodID(cls2, "run", "()V");  // find method
        if(mid == nullptr)
            cerr << "ERROR: method void mymain() not found !" << endl;
        else {
            cout << "===Call to java==================" << endl;
            env->CallStaticVoidMethod(cls2, mid);                      // call method
            runCocoaMain();
            cout << "===End of call to java==========="<<endl;
        }
    }
    // End JAVA calls ==================================================================
    jvm->DestroyJavaVM();
    cout << "Press any key...";
    cin.get();
}

J'aimerai savoir s'il existe une solution pour faire passer le thread courant pour le thread principale, ou alors une façon détournée d'atteindre mon but.

Merci par avances pour vos réponses.