fenetre "texte" genre console

cyranocyrano Membre
05:51 modifié dans Vos applications #1
bonsoir,

j'ai une application c++ (monothread) en mode console (les sorties se font par std::cout).
desirant passer au multithread, les sorties se melangent dans la console (plas glop).

quel est la meilleure solution pour creer une sortie pour chaque thread. une fenetre "texte" par thread est l'ideale. On doit sortir l'api cocoa et obj-c pour cela (que je ne connais pas) et interfacer avec mon code c++ ?

merci de vos sugestions

Réponses

  • AliGatorAliGator Membre, Modérateur
    janvier 2006 modifié #2
    Oh, un nouveau !
    T'es bon pour nous offrir une tournée générale, c'est la règle ici  :)
    Allez hop hop hop :p :p :p :p :p :p :p :p :p

    ----
    Bon, pour ton problème, oui tu peux créer une interface graphique pour interfacer ton code C/C++, et remplacer tes std::cout par des appels à  des méthodes Cocoa qui vont rajouter le texte dans la fenêtre adéquate. C'est le plus simple.
    Mais si tu ne connais pas Cocoa et n'en a jamais fait, entre autres que tu n'as jamais touché à  InterfaceBuilder, ça ne va pas forcément te sembler évident au premier abord. Alors qu'en soit c'est pas bien méchant ;)
    ----

    Autre solution, pure-C
    Sinon côté C++-only, moi je m'orienterai vers les pipes nommées (named pipes), qui me semble une solution assez simple.
    Tu crées tes pipes nommés (fichiers) pour la sortie (avec "mkfifo", dans le Terminal ou en code C au choix), une pipe par thread.
    Ensuite chaque thread écrit dans le pipe qui lui est associé (à  la place de ton std::cout), comme ça tu écris dans des flux séparés

    Après pour voir chaque sortie, tu ouvres une fenêtre terminal par thread, et tu tapes "cat nomDuFichierPipeNomméQueTuVeuxLire". et ça va lire en direct, en affichant le texte au fur et à  mesure qu'il arrive.

    C'est bien différent que d'écrire dans un simple fichier régulier (séquentiel) car dans le cas de pipes, le "cat" va toujours attendre de nouvelles données et non pas s'arrêter à  la "fin" du fichier (un tube n'est pas un fichier séquentiel, il n'a pas de "EOF")

    En plus en C c'est pas dur à  faire :
    #define LOG(_fd_,_str_) write(_fd_,_str_,strlen(_str_))<br /><br />/* Ouvrir le pipe nommé (à  faire au début du thread) */<br />int fd1 = open(&quot;/tmp/thread1pipe&quot;, O_WRONLY); // le pipe nommé doit exister<br /><br />/* écrire le texte logtext (char*) */<br />write(fd1, logtext, strlen(logtext));<br />/* utiliser la macro LOG pour rendre ça plus simple encore */<br />LOG(fd1,&quot;Coucou, je suis le thread 1&quot;);<br /><br />/* Fermer le pipe nommé (à  faire à  la fin du thread) */<br />close(fd1);
    
  • AliGatorAliGator Membre, Modérateur
    janvier 2006 modifié #3
    Bon allez petite mise à  jour car depuis j'ai essayé :

    Un programme à  la con pour te montrer (j'ai utilisé fopen plutôt que open car je trouve que c'est plus simple à  manipuler, avec fprinttf & co ça facilite les choses)
    #include &lt;stdio.h&gt;<br />#include &lt;errno.h&gt;<br />#include &lt;ctype.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/stat.h&gt;<br />#include &lt;fcntl.h&gt;<br /><br /><br />int main(int argc, char* argv&#91;])<br />{<br />  FILE* pipe1 = fopen(&quot;./flux1&quot;,&quot;w&quot;);<br />  FILE* pipe2 = fopen(&quot;./flux2&quot;,&quot;w&quot;);<br />  FILE* pipe3 = fopen(&quot;./flux3&quot;,&quot;w&quot;);<br /><br />  int i;<br />  for(i=0;i&lt;100;i++)<br />  {<br />    fprintf(pipe1,&quot;Thread 1 : %d&#092;n&quot;,i);<br />    fprintf(pipe2,&quot;Thread 2 : %d&#092;n&quot;,i);<br />    fprintf(pipe3,&quot;Thread 3 : %d&#092;n&quot;,i);<br />  }<br /><br />  fclose(pipe1);<br />  fclose(pipe2);<br />  fclose(pipe3);<br />}<br />
    
    Ce bout de code  montre juste comment très simplement remplacer tes std::cout par un simple sprintf. Note : avec ce code j'ai ouvert les pipes en mode bloquant (mode par défaut), donc les lignes fprintf vont bloquer le programme tant que les pipes ne seront pas lues et vidées (quel que soit le moyen, code C ou directement dans le terminal). Si tu ne lis pas les flux, le code ne continuera pas.
    Si tu veux du non-bloquant, utilises plutôt open et les flag O_WRONLY|O_NONBLOCK

    Bon, il te suffit de compiler ce code avec gcc, puis tu ouvres 4 fenêtres terminal : 1 par pipe que tu veux lire (qui seront les sorties de tes threads dans ton code final), et un pour lancer l'appli.
    • Dans la fenêtre 1, il faut créer le pipe nommé (je n'ai pas mis dans le code C de quoi le créer s'il n'exitait pas pour commencer simple, mais c'est aussi faisable par code), puis lire ce pipe.
      • Pour cela, tape la commande "mkfifo ./flux1" ce qui va créer le fichier en tant que pipe nommé
      • Ensuite, tape "cat flux1" pour lui demander de lire le pipe (il ne s'arrêtera que lorsque la pipe sera refermée du côté de l'écriture, ou que tu tapes ctrl-C)

    • Dans la fenêtre 2, pareil pour le pipe nommé 2 (pour ton 2e thread, à  terme) :
      • Taper "mkfifo ./flux2", valider
      • Taper "cat flux2" pour lui demander de commencer à  lire le pipe, et afficher le contenu au fur et à  mesure qu'il arrive du texte.

    • Pareil dans la fenêtre 3
    • Et enfin, tes 3 fenêtres sont prêtes et n'attendent plus que les pipes nommés soient remplis par des données. Donc tu executes le programme fraà®chement compilé, et tu admires  8)
  • cyranocyrano Membre
    05:51 modifié #4
    un grand merci 
    dans un premier temps, je vais implementé les named pipes (simple et rapide a mettre en oeuvre). je n'abandonne pas l'idee de le faire avec cocoa.

    passes prendre un verre  :p

    j'ai lu dans ta bio que tu as fait du Qt, qu'en penses tu par rapport a cocoa quand on programme en c++.

  • AliGatorAliGator Membre, Modérateur
    05:51 modifié #5
    Pour répondre à  ta question côté QT (petit curieux  :)) :
    - Je trouve ça quasi aussi sympa que Cocoa côté "approche de programmation"
    - Par contre c'est pur C++ (y'a des ponts possibles mais c'est C++ à  la base), alors que Cocoa c'est Objective-Cocoa. Les concepts ne sont pas les mêmes (messages envoyés aux objets, outlets, ... contre signals et slots)
    - L'approche est un peu différente mais ni mieux ni meilleure, chacune se vallent
    - Par contre le framework QT, bien que très complet, l'est moins que Cocoa
    - Mais en contrepartie il est cross-plateform ;)

    Donc c'est kifkif.
    Moi si je fais du Cocoa, c'est pour avoir des applis intégrés à  OSX, et pour pouvoir utiliser Cocoa (dans toute son intégration à  OSX)
    Mais si j'ai à  faire du C++ en crossplateform, j'utilise QT.
  • AntilogAntilog Membre
    05:51 modifié #6
    dans 1136412543:

    ...
    alors que Cocoa c'est Objective-Cocoa. Les concepts ne sont pas les mêmes
    ...


    Fayot !  :kicking:

    Cocoa, ce ne serait pas plutôt Objective-C?
    ;)
  • AliGatorAliGator Membre, Modérateur
    05:51 modifié #7
    Oups, lapsus révélateur ;D
  • cyranocyrano Membre
    05:51 modifié #8
    bonjour,

    on m'a conseillé, un simple fichier texte et la cmd tail -f.

    encore plus simple  ;)
  • AliGatorAliGator Membre, Modérateur
    05:51 modifié #9
    Ah oui, aussi....
    Pourquoi faire simple quand on peut faire compliqué, hein ? :D
Connectez-vous ou Inscrivez-vous pour répondre.