2015-09-21 1 views
1

Je travaille avec SDL et j'ai presque résolu tous les problèmes que j'ai.Android JNI et NewGlobalRef

Je lance un appel jni pour init le framework, puis en crée une référence globale car c'est la meilleure façon de penser pour le moment.

La plupart de mes fonctions JNI utilisent les variables d'instance, sauf une pour lire les fichiers. Voici comment je configure le globalref.

JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jobject instance) 
{ 
    Android_JNI_SetupThread(); 
    mInstance = instance; 

    jclass clazz = (*mEnv)->GetObjectClass(mEnv, instance); 
    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, clazz)); 
..... 
} 

Je n'utilise que cette référence mondiale mActivityClass deux fois dans ce code pour lire faire des fonctions qui peuvent être appelées à tout moment.

La question principale, spécifiquement pour android JNI. Si je maintiens ce globalref, puisque android contrôle le cycle de vie de l'application, ref va provoquer la reprise de mon application même si j'essaye de quitter.

Si j'essaie d'effacer ce globalref avec quelque chose comme DeleteLocalRef, l'application semble toujours vouloir reprendre au lieu de quitter. Y a-t-il un moyen d'arrêter ce comportement? Une autre question, est-il possible de créer une fonction JNI non statique qui est appelée du côté c du monde de code, de sorte que je puisse obtenir une instance jobject et l'utiliser pour obtenir une instance de l'instance de classe?

Par exemple vous écrivez en général une fonction java:

public native void do_c_work(); 

côté c:

void Java_com_test_java_do_c_work(JNIEnv* env, jobject inst) 
{ 
    ...use the instance do your work 
} 

si certaines fonctions s'appelle du côté c, que je voudrais obtenir une instance de Java pour faire quelque chose avec.

fonction

c:

public int get_number(); 

Je suis un peu coincé ici, je ne veux pas instancier un nouvel objet java à ce moment, principalement parce i saw this et il semble exagéré.

Il doit y avoir un moyen de surmonter cet obstacle, soit en étant capable d'appeler java depuis c sans utiliser de statique ou en créant une nouvelle activité, il y en a déjà un ou libérer le globalref mais cela ne semble pas marcher si bien pour moi en ce moment.

Répondre

-1

Quel est le but de détenir un GlobalRef à un jclass? Si c'est seulement ainsi vous pouvez obtenir methodIDs, les obtenir maintenant dans ce code, et les stocker. Ils ne sont que des ints, pas des références d'objets, donc vous n'avez pas besoin de GlobalRef quoi que ce soit.

+0

Je reçois des jobjects avec cette référence, j'ai besoin d'obtenir le contexte d'application qui est jobject ainsi que jmethodID, ex: jmethodID mid = (* env) -> GetStaticMethodID (env, mActivityClass, "getContext", "() Landroid/contenu/contexte; "); | jobject context = (* env) -> CallStaticObjectMethod (env, mActivityClass, mi); – user1610950

0

Quelques notes:

  1. JNI références mondiales ne forcez pas votre application pour rester ouvert. Le garbage collector les connaît, mais le framework d'application qui contrôle le cycle de vie ne l'est pas. Il existe de nombreuses références globales créées par le framework d'application lui-même. (Les applications ne sont pas "collectées".)

  2. Si vous souhaitez supprimer une référence globale, utilisez DeleteGlobalRef, et non DeleteLocalRef.

  3. Si vous souhaitez appeler des méthodes de langage Java non statiques à partir de C, passez l'objet au code natif et invoke a method dessus. Créez une référence globale pour le jobject si vous l'utilisez après le retour de la méthode native sur la machine virtuelle. (Je me sens comme peut-être je ne comprends pas cette partie de la question.)

Voir aussi JNI Tips et JNI spec.