Bonsoir tout le monde,
Je suis bloqué depuis plusieurs jours sur un point de programmation que je n'arrive pas à résoudre, et malheureusement google ne m'aide pas beaucoup (enfin du moins j'arrive pas à lui demander suffisemment gentilment pour qu'il me réponde correctement).
Donc voila mon probleme :
J'ai un logiciel simple en lignes de commandes qui fait une succession de 'scanf' et 'printf' (ou equivalent) : en l'occurence ce soft est crafty (jeu d'échec) qui commence par demander notre deplacement d'une piece, puis repond si le coup est accepté et enfin repond le coup de l'IA.
Et j'aimerais faire une GUI sur ce programme. Mais voila je ne trouve pas du tout comment faire.
J'ai tenté la creation de 2 pipes (un pour les saisies, et lautre pour récupérer les donnees affichees en sortie) avec un fork et execlp pour communiquer entre mon programme et crafty, mais je suis tombé sur un probleme : le pipe de sortie ne me donne les differents textes *seulement* quand crafty est completement terminé. Or j'aimerais pouvoir recuperer les infos au fur et a mesure des saisies.
Donc si quelqu'un pouvait m'aider ca serait vraiment super.
Peut etre faut-il utiliser autre chose que les pipes ? j'ai testé avec 'popen()' (mais il limite a l'écriture *ou* la lecture, mais pas les 2 en meme temps) et j'ai le même problème :(
Peut etre que j'ai mal implementé mes pipes ?
Merci d'avance pour vos réponses.
# expect
Posté par mac_is_mac (site web personnel) . Évalué à 1.
http://www.tcl.tk/man/expect5.31/libexpect.3.html
# je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par Pol' uX (site web personnel) . Évalué à 2.
Si jamais ton problème viens de la, une solution radicale est de désactiver la mémoire tampon pour stdout : setbuf (stdout, NULL);
Sinon, en alternative aux pipes,il existe les fifo (tubes nommés) : man mkfifo
Sinon, ca peut etre intéressant de faire une GUI dans un processus séparé (comme tu fait, quoi !) mais pourquoi ne pas tout mettre dans le meme processus ? au besoin, si tu doit faire de l'exécution concurente, les threads sont faits pour cela, c'est simple à mettre en oeuvre, et ca possède le meme espace d'addressage mémoire ; fini la communication par pipe ! (mais bonjour la synchronisation ...)
http://yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Bonne chance ...
Adhérer à l'April, ça vous tente ?
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par NeoWerner . Évalué à 2.
2/ pour le \n dans printf, j'ai deja testé, mais pas mieux. :(
3/ sinon les threads je connais, en effet c'est bien pratique pour faire des executions en parallele (notament des ecritures d'un coté pendant qu'il attends qu'une donnee lui parvienne). Ceci marche tres bien lorsque je fais des tests sur d'autres domaines : genre ports series ou sockets. Mais mon probleme n'est pas la.
Je vais prendre un exemple simple :
programme de test executé : printf("coucou\n"); sleep(10); printf("test\n");
dans le programme d'execution de ce dernier, je fais une boucle sur un read() et j'affiche tout ce qui arrive. Mais je ne recois le "test" comme le "coucou" seulement 10sec apres son execution (soit quand le prog de test a quitté).
Sinon tu me dis de tester en laissant tout dans le meme processus, mais comment puis-je recuperer les pointeurs de fichiers vers l'entree et la sortie du programme executé (crafty) ? (pour faire des read() et write() dessus)
4/ Sinon j'ai regardé le man du mkfifo, ca peut en effet etre une bonne solution : le principe serait de faire 2 fifo (fichiers 'virtuels') et d'ouvrir ces 2 "fichiers" dans ma GUI c'est bien ca ? ( avec un exec("fifo1 > crafty > fifo2") ) ?
merci beaucoup pour ton aide :)
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par Pol' uX (site web personnel) . Évalué à 2.
Quand je disais de tout mettre dans le processus, j'entendais par là réécrire un programme, avec GUI (perso j'aime bien GTK) qui fait ce que crafty fait. Vu que tu dit que crafty est simple, ca ne sera pas a priori très compliqué. En tout cas, je trouve ca plus propre.
Regarde du coté de libglade, ca peut te permettre d'adapter ton code très simplement : dans le processus crafty, tu fait un thead pour gtk_main() et un thread pour ton traitement de crafty. Tu remplace les entrées et sorties standarde par des variables ... et tu as juste à rajouter les fonctions de callback.
Adhérer à l'April, ça vous tente ?
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par NeoWerner . Évalué à 1.
En fait j'ai testé avec les fifo, et jai le meme probleme. Par exemple j'ai cree un programme de test qui fait :
test.c : main() { printf("coucou"); sleep(10); printf("yo"); }
ensuite je lance le tout :
$ gcc -o test test.c
$ mkfifo ./fifotest
$ ./test > ./fifotest
et dans un autre terminal :
$ cat ./fifotest
ou
$ tail -f ./fifotest
et je recupere les donnees seulement apres les 10sec :( j'arrive pas a avoir le "coucou" avant la fin de l'execution du programme.
par contre si dans mon test.c je rajoute au debut ce que tu me disais dans ton message precedent : setbuf (stdout, NULL); ca marche super bien. mais ca implique que je modifie les sources de crafty pour rajouter juste une ligne ;) je comprends pas comment ils font les autres sans ca :p
j'en conclus donc que de base, le stdout a un buffer, et ce buffer serait peut etre recuperable dans mon code directement ?
Sinon ouai je crois que je vais finir par prendre les sources de crafty et y implementer ma GUI directement, mais si il y a des nouvelles versions de crafty c'est moins pratique.
Pour GTK je connais aussi, c'est ce que je prefere aussi ;)
merci :)
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par durandal . Évalué à 1.
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par NeoWerner . Évalué à 1.
j'ai essayé de lire et relire les sources où je pense que ca parle de tout ca (où il y a un fork et un exec de crafty) mais je comprends vraiment pas.
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par JaguarWan . Évalué à 3.
jaguarwan@Jaguar:~$ gcc -std=c99 -posix -pedantic -Wall coincoin.c
jaguarwan@Jaguar:~$ ./a.out
fiston est ne !
papa est la.
(0) le fiston dit: plop ! plop !
(1) le fiston dit: gruiiiiiik
(2) le fiston dit: coincoin ?!
papa a repondu: pan ! pan !
**argh**
jaguarwan@Jaguar:~$
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par NeoWerner . Évalué à 1.
merci pour ton code. J'ai testé comme tu l'as mis : ca marche impect. Mais j'ai toujours le meme probleme :
j'ai exporté la partie enfant dans un autre programme './test' puis je l'ai executé avec un execve.
Si je mets le setbuf(stdout, NULL) dans mon programme test, aucun probleme, ca marche toujours impec. Mais si je l'enleve (ce qui est le cas dans la majorité des programmes), bhen ca remarche plus :(
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par JaguarWan . Évalué à 2.
Je pense que pour être tranquille il faudrait utiliser une paire de pty et bricoler l'esclave en mode non canonical pour qu'il renvoie ses données sans faire de buffering, mais là c'est un peu plus compliqué à écrire que mon petit programme bidon de tout à l'heure.
Je laisse donc ça en exercice aux lecteurs :]
Voilà qui pourra t'être utile:
http://www.tnt.uni-hannover.de/soft/case/lang/c/libc/libc_17(...)
Allocation de pseudo terminaux:
http://www.tnt.uni-hannover.de/soft/case/lang/c/libc/libc_to(...)
Un bout de code pour mettre un terminal en mode non canonique, sans echo et qui lit caractères par caractères:
http://www.tnt.uni-hannover.de/soft/case/lang/c/libc/libc_to(...)
Si tu te fous de la portabilité, l'appel:
int forkpty (int *amaster, char *name, struct termios *termp, struct winsize *winp)
fait un peu le café.
(http://www.tnt.uni-hannover.de/soft/case/lang/c/libc/libc_to(...) )
[^] # Re: je ne sais pas si j'ai bien saisi ton problème, mais bon ....
Posté par NeoWerner . Évalué à 1.
Je vais me pencher la dessus, merci beaucoup pour ton aide.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.