7
votes

Comment devrais-je écrire le fichier .i pour envelopper les rappels dans Java ou C #

Mon programme C utilise des fonctions de rappel qui sont appelées périodiquement. Je veux pouvoir gérer les fonctions de rappel dans un programme Java ou C #. Comment devrais-je écrire le fichier .Je pour y parvenir?

Le raclage C a l'air: P>

static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)


4 commentaires

Votre rappel a-t-il un argument de données void * ?


Le rappel dans C Look So: Statique Void On_incoming_Call (PJSUA_ACC_ID ACC_ID, PJSUA_CALL_ID Call_ID, PJSIP_RX_DATA * RDATA)


Qu'est-ce que pJSIP_RX_DATA - A TypeDEF pour VOID * ? Une structure? (En essayant de déterminer si nous pouvons passer un Jobject autour du rappel de manière triviale)


Claudio, pourquoi ne pas accepter la réponse, car elle flotte depuis 3 ans.


3 Réponses :


-3
votes

C # Solution: Vous devez utiliser les délégués. Regardez l'exemple de code

interface Notification{
      public void somthingHappend(Object obj);
}

class MyClass{
     private Notification iNotifer;

     public void setNotificationReciver(Notification in){
            this.iNotifier = in;
     }

     public void doWork(){
            //some work to do
            if(something heppens){ iNotifier.somthingHappend(something);}
     }
}


0 commentaires

24
votes

Vous pouvez le faire si vous avez une chance de passer des données avec le rappel, mais vous devrez écrire une colle JNI. Je mets ensemble un exemple complète de la manière dont vous pourriez mapper des rappels de style C sur une interface Java.

La première chose à faire est de décider d'une interface appropriée sur le côté Java. J'ai supposé que dans C nous avions des rappels comme: p> xxx pré>

J'ai décidé de représenter cela en Java comme: p> xxx pré>

(le Perte du Void * userData ​​code> du côté Java n'est pas un problème réel car nous pouvons stocker l'état dans l'objet code> code> qui implémente rappel code> trivialement) . P>

J'ai ensuite écrit le fichier d'en-tête suivant (il ne faut pas vraiment être un en-tête, mais cela empêche les choses simples) d'exercer l'emballage: P>

public class run implements Callback {
  public void handle(int val) {
    System.out.println("Java callback - " + val);
  }

  public static void main(String argv[]) {
    run r = new run();

    System.loadLibrary("test");
    test.set(r);
    test.dispatch(666);    
  }
}


13 commentaires

Merci pour la réponse détaillée. Je cherchais exactement quelque chose comme ça.


+1 Pour l'exhaustivité de la solution, mais j'ai remarqué que vous faites un masloc sans correspondant gratuit . (Ou est-il implicitement libéré quelque part?)


@ZUB Je pense que c'était ce que je voulais dire par point 1 dans la dernière liste. Je vais essayer de creuser cela au cours de la fin de semaine pour développer ce point.


Est-il possible d'éviter Set / Dispatch Paradigm mais faire quelque chose comme ça - Vide natif (Callback_T cb, int Arg1, int Arg2, Void * place_result_on_arg1_arg2_here) {cb (arg1, arg2, place_result_on_arg1_arg2_HERE) ; } J'ai essayé mais arg1 et arg2 reste unialistialisé dans _wrap.cxx fichier. Une seule solution que j'ai trouvée avoir des champs appropriés dans exécuter la classe et les utiliser au lieu des arguments vides passés.


@triclosan - probablement possible mais je ne comprends pas tout à fait la sémantique de ce que vous essayez de faire. Vous pouvez fusionner l'ensemble / envoi de mon exemple en un, mais vous auriez besoin d'utiliser un global pour contenir une référence à l'instance Java, vous souhaitez exécuter le rappel. Vous voulez éventuellement demander une question de suivi avec un exemple complet mais simple du côté C de l'API? (N'hésitez pas à me piquer sur chat ou ici si vous le faites)


J'ai fait une question séparée Stackoverflow.com / Questions / 20719497 / ...


Bonjour @flexo! J'ai suivi votre réponse, mais je ne sais pas pourquoi je reçois cette erreur: exception dans le fil "Main" Java.lang.unsatisfiedLinkError: mon / pkg / to.testjni.set (lmy / pkg / to / rappel;) v


@Farah - à une supposition, je dirais que vous n'avez pas l'interface rappel dans le bon package, ou accidentellement fabriqué par hasard.


@Flexo Il y a quelque chose qui me échappe: comment puis-je récupérer l'UserData du côté Java?


@celavek vous n'en avez pas besoin en Java, l'objet qui reçoit le rappel est un objet approprié afin qu'il puisse avoir des membres que vous aimez. Utilisez cela à la place, plus de OO, plus flexible.


@Flexo Mais je voudrais passer des données significatives de C à Java via le paramètre de rappel. Alors, comment pourrais-je avoir cela via l'objet qui reçoit le rappel? Je sais comment faire ça via Jni codé à la main mais j'ai passé le dernier jour à essayer de le faire via Swig.


@celavek passe comme un paramètre à la fonction comme je l'ai fait avec l'argument int . Abuser le Callback UserData n'est définitivement pas le moyen de transmettre l'état à un objet Java.


Excellente réponse. Cela fonctionne comme indiqué, comment le faire fonctionner lorsque les arguments de la fonction sont des pointeurs S'il vous plaît voir la question



2
votes

C ++ à C # Exemple de rappel

Ceci fonctionne bien pour permettre à C ++ d'exécuter des rappels sur C #.

Testé sous:

  • c # : Visual Studio 2015
  • C ++ : Intel Parallel Studio 2017 SE
  • c ++ : devrait fonctionner bien pour Visual Studio 2015 C ++ (quelqu'un peut-il vérifier cela?).
  • C ++ : doit fonctionner bien pour tout autre compilateur Windows C ++ qui génère une standard .dll (quelqu'un peut-il vérifier cela?).

    dans votre Swig .Je fichier, incluez ce fichier callback.i : xxx


0 commentaires