Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Rediriger stderr vers une fonction

9 réponses
Avatar
cLx
Bonjour,

J'ai dans mon programme et pas mal de ses modules des messages d'erreurs qui
sont envoyés avec fprintf(stderr, ...);.

Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serait-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?

Merci,

--
cLx

9 réponses

Avatar
Jean-Marc Bourguet
cLx 'aimail.com.almost.invalid> writes:

J'ai dans mon programme et pas mal de ses modules des messages d'erreurs qui
sont envoyés avec fprintf(stderr, ...);.

Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serai t-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?



Rien en standard. Glibc a une notion de "custom stream" (voir le
manuel) mais c'est donc pratiquement que sous Linux et je n'ai pas le
souvenir de quelquechose d'equivalent ailleurs.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Xavier Roche
Le 23/08/2011 14:20, cLx a écrit :
Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serait-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?



Il suffit de reassigner le handle 2 (pour stderr - ou 1 pour stdout)
vers autre chose, comme.. un pipe, et de créer un thread qui ira lire
dessus:

const int errFd = 2;
int pipeFds[2];
if (pipe(pipeFds) == 0) {
const int rFd = pipeFds[0];
const int wFd = pipeFds[1];
if (dup2(wFd, errFd) == 0) {
.. créer un thread de fond pour lire les données depuis rFd
} else {
.. blah
}
} else {
.. blah
}
Avatar
Xavier Roche
Le 23/08/2011 14:20, cLx a écrit :
Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serait-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?



Il suffit de reassigner le handle 2 (pour stderr - ou 1 pour stdout)
vers autre chose, comme.. un pipe, et de créer un thread qui ira lire
dessus:

const int errFd = 2;
int pipeFds[2];
if (pipe(pipeFds) == 0) {
const int rFd = pipeFds[0];
const int wFd = pipeFds[1];
if (dup2(wFd, errFd) == 0) {
close(wFd);
.. créer un thread de fond pour lire les données depuis rFd
} else {
.. blah
}
} else {
.. blah
}
Avatar
Xavier Roche
Le 23/08/2011 14:20, cLx a écrit :
Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serait-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?



Il suffit de reassigner le handle 2 (pour stderr - ou 1 pour stdout)
vers autre chose, comme.. un pipe, et de créer un thread qui ira lire
dessus:

const int errFd = fileno(stderr); /* en théorie 2 :) */
int pipeFds[2];
if (pipe(pipeFds) == 0) {
const int rFd = pipeFds[0];
const int wFd = pipeFds[1];
if (dup2(wFd, errFd) == 0) {
close(wFd);
.. créer un thread de fond pour lire les données depuis rFd
} else {
.. blah
}
} else {
.. blah
}
Avatar
cLx
On 23/08/2011 14:41, Jean-Marc Bourguet wrote:
Rien en standard. Glibc a une notion de "custom stream" (voir le
manuel) mais c'est donc pratiquement que sous Linux et je n'ai pas le
souvenir de quelquechose d'equivalent ailleurs.



OK, donc pas trop portable.. Merci.
Avatar
cLx
On 23/08/2011 15:23, Xavier Roche wrote:
Le 23/08/2011 14:20, cLx a écrit :
Le truc c'est que maintenant qu'on fait une belle interface avec Curses, on
voudrait afficher les messages d'erreur dans une fenêtre pour. Serait-il
possible de rediriger stderr (et stdout) vers une fonction, même via un pipe,
un peu comme freopen mais pas vers une fichier ?



Il suffit de reassigner le handle 2 (pour stderr - ou 1 pour stdout)
vers autre chose, comme.. un pipe, et de créer un thread qui ira lire
dessus:

const int errFd = fileno(stderr); /* en théorie 2 :) */
int pipeFds[2];
if (pipe(pipeFds) == 0) {
const int rFd = pipeFds[0];
const int wFd = pipeFds[1];
if (dup2(wFd, errFd) == 0) {
close(wFd);
.. créer un thread de fond pour lire les données depuis rFd
} else {
.. blah
}
} else {
.. blah
}




Merci pour votre réponse.

Sous Linux et NetBST ça marche ! mais sous windows (gcc et sans gygwin), il
me manque cruellement pipe().
Avatar
Xavier Roche
Le 23/08/2011 15:37, cLx a écrit :
Sous Linux et NetBST ça marche ! mais sous windows (gcc et sans gygwin), il
me manque cruellement pipe().



Il faut utiliser la variante _pipe()
http://msdn.microsoft.com/en-us/library/edze9h7e%28v=vs.71%29.aspx
Avatar
Antoine Leca
Xavier Roche écrivit :
const int errFd = fileno(stderr); /* en théorie 2 :) */



On peut aussi alourdir (?) avec STDERR_FILENO }:->


Antoine
Avatar
Mickaël Wolff
On 23/08/11 14:20, cLx wrote:
Bonjour,

J'ai dans mon programme et pas mal de ses modules des messages d'erreurs qui
sont envoyés avec fprintf(stderr, ...);.



Si l'ensemble des appels à fprintf sur stderr doivent aterrir dans
une fenêtre de log, peut-être que tu pourrais simplement faire un grep
sur l'ensemble du projet :


find . -name '*.c' -exec
sed -i 's/bfprintf(stderr, /log_error(/' {} ;

Bien sûr il faut une fonction dans ce style là (implémentation naïve,
je ne suis pas convaincu que ce soit canonique, les variadiques à la C
me rendent nerveuses) :

int log_error(char * fmt, ...)
{
int ret = 0 ;
va_list args ;
va_start(args, fmt) ;
ret = vfprintf(stderr, fmt, args) ;
va_end(args) ;
return ret ;
}