IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

Les boucles et GTK.


Sujet :

GTK+ avec C & C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Electronicien
    Inscrit en
    Janvier 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Electronicien

    Informations forums :
    Inscription : Janvier 2015
    Messages : 3
    Points : 7
    Points
    7
    Par défaut Les boucles et GTK.
    Bonjour,

    J'ai récemment voulu ajouter une interface graphique à certains de mes petits programmes en C++ sous Code::Blocks (Windows). GTK+ (intégré à Code::Blocks) m'étant apparu comme accessible j'ai donc fait quelques test ma fois plutôt concluants, puis (et c'est là que ça devient problématique) est arrivé le moment où il a fallut faire cohabiter GTK et les programmes.

    Pour faire simple, j'ai des programmes "clients" qui récupèrent l’état de capteurs et envoient des commandes (via Nudam ou récemment testé avec des Raspberry). A noter que ces programmes ne prennent aucune décisions puisqu'ils envoient l'état des capteurs en UDP à un poste central et reçoivent en retour des instructions pour leurs sorties.
    Ceci nous amène au programme "serveur" qui collecte les données envoyées par les clients et "décide" des actions à leur faire effectuer.

    Coté client, pas de soucis.
    Coté serveur le programme était de la forme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    boucle principale{
       écoute des transmissions clients
       si réception d'info{fonction "décisionnelle" incluant l'envoi d'ordres}
       toutes les x secondes{fonction de demande d'info aux clients}
    }
    les diverses fonctions
    Si j'ai bien suivi le fonctionnement de GTK j'ai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    boucle principale{
       Construction de l'interface GTK avec les callbacks
       Lancement de la boucle GTK
    }
    les diverses fonctions callback
    Sur le principe j'ai bien réussi à faire une fenêtre, répercuter les actions (sur des boutons par exemple), pas de problème. Ce qui m'échappe en revanche c'est comment écouter mes sockets en permanence pour réagir en fonction comme je le faisait. J'ai bien trouvé des références à ce problème sur divers forum mais (et ça vient peut-être de moi) je n'ai rien compris du tout.


    Si quelqu'un a de quoi éclairer ma lanterne.

  2. #2
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 597
    Points : 7 832
    Points
    7 832
    Par défaut
    Si tu plaçais sur l'évènement ouverture de la fenêtre le lancement de ta boucle de lecture des différents capteurs ?
    Modérateur Mageia/Mandriva Linux
    Amicalement VOOotre
    Troumad Alias Bernard SIAUD à découvrir sur http://troumad.org
    Mes tutoriels : xrandr, algorigramme et C, xml et gtk...

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    j'entrevois trois solutions possibles :

    1. insérer dans la boucle principale de Gtk+ la fonction de lecture des capteurs,
    2. utiliser les threads,
    3. créer deux applications distinctes qui communiquent entre-elles.


    Pour la première solution l'inconvénient majeur et que la lecture n'est pas continue. Lorsque les widgets ont besoin de se rafraîchir pour une raison ou pour une autre la boucle de lecture est forcément en attente. Si les données sont continuent il y aura naturellement perte d'information à l'arrivée.

    La deuxième solution répond au problème de la première. Mais il est difficile de faire cohabiter deux threads distinctes et surtout interagir l'un vers l'autre. Mais ce n'est impossible.

    La troisième solution à ma préférence. Puisque tu disposes déjà d'une application console capable de lire les données il suffit de créer une application indépendante Gtk+ qui va lancer en interne l'application console. En faisant cela tu pourras déclarer des interruptions logicielles qui liront les informations transmises dés qu'elles sont disponibles. Ces informations reçus tu pourras les afficher ou en faire ce que tu veux.
    Les fonctions associées pour réaliser tout ceci sont les GIOChannel.

  4. #4
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Je suis un peu une buse en sockets, mais j'ai fait mes devoirs et cherché un peu sur le web .
    Je dirais donc:
    - pas de thread si la montée en charge ne le nécessite pas. Le multithreading complique la programmation et le debugging, si on peut s'en sortir juste avec de la programmation événementielle, on le fait.
    - créer un frontend graphique à un outil existant peut être intéressant s'il y a un usage du programme déjà existant en ligne de commande. Si ce n'est pas intéressant de l'utiliser en ligne de commande, c'est en général plus simple de tout mettre dans l'application graphique.

    Pour bien répondre, il faut savoir comment tu as développé la partie serveur côté réception des événements sockets. En effet, tu ne peux pas te permettre de faire des appels bloquants si tu dois intégrer cela à la bouclé d'événements GTK+. Donc actuellement tu dois sans doute utiliser select, poll ou epoll pour cela, ou bien tu fais directement des appels bloquants avec recvfrom vu que tu fais de l'UDP. Si tu utilises select, poll ou epoll, tu as déjà moyen de faire du non-bloquant, en utilisant juste un timeout nul. Mais vu la question que tu poses, j'imagine que tu fais plutôt des appels bloquants avec recvfrom. Donc il faut que tu transformes les appels bloquants de ta boucle infinie en appels non bloquants.

    Pour cela il y a plusieurs solutions, évoquées ici: https://stackoverflow.com/a/2332303/518853
    La plus simple sera sans doute d'appeler recvfrom en lui disant de ne pas bloquer en attente de données grâce à fcntl, voir la page de manuel de recvfrom:

    If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)), in which case the value -1 is returned and the external
    variable errno is set to EAGAIN or EWOULDBLOCK. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.
    Une fois que ça marche de cette manière en asynchrone, l'intégration dans la boucle d'événements de GTK+ est triviale. Tu as juste à ajouter une nouvelle source d'événements à la boucle d'événements de GTK+. Cela te permet d'appeler une callback de ton choix quand GTK+ n'a plus d'événement à traiter, ton code sera donc appelé régulièrement, comme si tu étais dans ta boucle infinie. Tu utiliseras pour cela g_idle_add, g_timeout_add ou g_timeout_add_seconds selon la fréquence à laquelle tu veux être appelé. Si tu n'as pas de régularité particulière (genre un message toutes les secondes), alors utilise g_idle_add. Dans la callback correspondant à ta source d'événements, tu appeleras ton recvfrom non-bloquant pour récupérer les données à lire (s'il y en a) et les traiter. Le traitement ne doit toutefois pas prendre trop de temps, car tant que tu es dans ta callback, GTK+ ne peut plus gérer d'autre événement vu que tu n'as qu'un seul thread, le thread principal. Donc tu dois traiter les informations et sortir rapidement de ta callback pour que GTK+ puisse reprendre la main. Ainsi tu n'auras pas de "gel" de l'interface quand tu redimensionnes la fenêtre par exemple.

    Bon courage
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

Discussions similaires

  1. [VBS]Bug sur les boucles for.
    Par méphistopheles dans le forum VBScript
    Réponses: 7
    Dernier message: 24/03/2006, 22h17
  2. Les Boucles
    Par Ghazuski dans le forum C
    Réponses: 13
    Dernier message: 15/11/2005, 08h46
  3. [SQL - procStock ] optimisation du code (éviter les boucles)
    Par luimême dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 06/10/2005, 17h22
  4. [Tableaux] Problème avec les boucles
    Par speed_man002 dans le forum Langage
    Réponses: 4
    Dernier message: 21/09/2005, 15h42
  5. [C#] Comment eviter les boucles infinies ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 12
    Dernier message: 09/06/2004, 00h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo