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)
3 Réponses :
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);}
}
}
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> J'ai décidé de représenter cela en Java comme: p> (le Perte du 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> 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> 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);
}
}
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 code> sans correspondant gratuit code>. (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 Code> 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) ; } code> J'ai essayé mais arg1 code> et arg2 code> reste unialistialisé dans _wrap.cxx code> fichier. Une seule solution que j'ai trouvée avoir des champs appropriés dans exécuter la classe code> 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 code> 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 code>. 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
Ceci fonctionne bien pour permettre à C ++ d'exécuter des rappels sur C #. P>
Testé sous: p>
c # code>: Visual Studio 2015 Li>
-
C ++ code>: Intel Parallel Studio 2017 SE LI>
-
c ++ code>: devrait fonctionner bien pour Visual Studio 2015 C ++ (quelqu'un peut-il vérifier cela?). Li>
-
C ++ code>: doit fonctionner bien pour tout autre compilateur Windows C ++ qui génère une standard .dll (quelqu'un peut-il vérifier cela?). LI>
ul> dans votre Swig .Je code> fichier, incluez ce fichier callback.i code>: p> xxx pré> h3 >
Votre rappel a-t-il un argument de données code> void * code>?
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 code> - ATypeDEF code> pourVOID * code>? Une structure? (En essayant de déterminer si nous pouvons passer unJobject code> autour du rappel de manière triviale)Claudio, pourquoi ne pas accepter la réponse, car elle flotte depuis 3 ans.