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

bibliotheque et fichiers d'en-tete pour l'utilisateur

50 réponses
Avatar
Vincent Lefevre
Bonjour et bonne année,

J'aimerais avoir votre avis sur le point suivant (je n'ai pas vu
d'indications dans les FAQ). Dans la bibliothèque qu'on développe
(MPFR), il y a des fonctions qui ne sont liées aucunement à la
bibliothèque standard et d'autres qui sont liées à certaines choses
de <stdio.h> (par exemple utilisent FILE en argument, parce que ce
sont des fonctions d'entrées/sorties). Y a-t-il une ou des solutions
recommandées concernant les fichiers d'en-tête fournis par la
bibliothèque (pour l'utilisateur de la bibliothèque), avec une
volonté de portabilité?

1) La solution actuelle est celle de GMP, qui est d'essayer de
détecter automatiquement si <stdio.h> a été #inclus avant gmp.h,
auquel cas gmp.h déclare les fonctions d'entrées/sorties. Mais cela
pose notamment deux gros problèmes: comme il n'y a pas de standard
pour cette détection, cela risque d'échouer sur les plateformes non
testées (et cela arrive en pratique) ou à cause de changements futurs
sur les plateformes existantes (cf tous les problèmes qu'a posés le
changement lié au errno dans la glibc); d'autre part, cette méthode
empiète sur le domaine de l'utilisateur. Par exemple, le programme
suivant ne compile pas:

#define H_STDIO 1
#include <gmp.h>

int main(void)
{
return 0;
}

(à noter que H_STDIO ne fait pas partie des macros réservées par GMP,
qui commencent par "GMP_", par convention).

2) Il y a la solution d'inclure systématiquement <stdio.h> dans le
fichier d'en-tête qu'on fournit (mpfr.h), éventuellement sauf si telle
macro, e.g. MPFR_NO_STDIO, est définie auparavant par l'utilisateur
(évidemment, tout cela devant être parfaitement documenté...).

3) Il y a la solution de fournir plusieurs fichiers d'en-tête, e.g.
mpfr.h et mpfrIO.h, où <stdio.h> n'est inclus que dans "mpfrIO.h".
C'est une sorte de (2) modulaire.

Dans les quelques bibliothèques que j'ai regardées (à part GMP), c'est
soit (2) sans la possibilité d'empêcher l'inclusion, soit (3).

Pour info, ma préférence personnelle va pour (3), pour son aspect
modulaire en particulier.

--
Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

10 réponses

1 2 3 4 5
Avatar
Vincent Lefevre
Dans l'article <btkrhu$ms4$,
Marc Espie écrit:

In article ,
Erwan David wrote:
Euh, je ne vois pas ce qui pourrais provoquer ça. Les problèmes
d'ordre d'inclusion apparaissent quand a.h n'inclus pas b.h mais n'est
pas parsable sans l'avoir inclus (par exemple parceque a.h déclare une
fonction utilisant un type déclaré dans b.h)
Les entetes qui parfois ont des definitions supplementaires que tu n'as

pas prevues, et qui posent des problemes de portabilite parce qu'elles
collisionnent avec d'autres choses, et uniquement sur certains systemes.


Mais dans ce cas, on peut se retrouver avec des contraintes
insatisfiables. Maintenant, l'inclusion de <stdio.h> dans notre
fichier d'en-tete n'empêche pas son inclusion en tout début du
fichier .c, auquel cas il ne devrait pas y avoir de problème en
pratique.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA


Avatar
Erwan David
Emmanuel Delahaye écrivait :

In 'fr.comp.lang.c', Erwan David wrote:

Non. Si tu es en freestanding tu n'utilise *pas* stdio.h
Jamais.


Je ne vois pas pourquoi. Je fais ça tous les jours depuis 10 ans. Je ne suis
pas mort...


DOnc tu dépends de la présence d'un stdio.h sur ta plateforme. Dans
mon cas, je ne peux pas compter dessus, donc je n'utilise pas, sauf
éventuellement dans les implémentations des fonctions qui dépendent de
la plateforme. S'il y a un stdio alors ces fonctions sont de simples
wrappers, mais l'appli n'accède jamais directement à stdio.


Avatar
Gabriel Dos Reis
Vincent Lefevre <vincent+ writes:

| > Quand tu travailles dans un freestanding, ce qui va te potentiellement
| > poser probleme, ce n'est pas FILE*, mais malloc() ou autres
| > joyeuseutes utilisees dans GMP. Ton FILE*, tu as juste besoin pour
| > declarer des fonctions; tu n'est pas oblige de les /definir/ si ton
| > environnement ne supporte pas les I/O avec FILE*.
|
| Pour le FILE *, je suppose qu'il est plus pratique alors pour l'utilisateur
| d'un tel système de créer un fichier stdio.h pour que tout se parse sans
| problème.

Oui, et c'est valide.

| Concernant le malloc(), on appelle pour le moment le wrapper de
| GMP, où l'utilisateur peut définir ses propres fonctions d'allocation, ce
| qui fait que cela ne posera pas forcément de problème.

OK.

-- Gaby
Avatar
Gabriel Dos Reis
Vincent Lefevre <vincent+ writes:

| Dans l'article ,
| Gabriel Dos Reis écrit:
|
| > Vincent Lefevre <vincent+ writes:
|
| > | On n'inclut pas <stdlib.h> dans mpfr.h.
|
| > Oui, mais si tu utilises GMP, tu utilises malloc() non ?
|
| On n'a aucun appelle à malloc().

« on » c'est ta biblio ou GMP ?

j'ai toujours compris que MPFR se basait sur GMP (c'est ce que j'ai
compris d'une presentation de Guillaume).

-- Gaby
Avatar
Vincent Lefevre
Dans l'article ,
Gabriel Dos Reis écrit:

Vincent Lefevre <vincent+ writes:

| On n'a aucun appelle à malloc().

« on » c'est ta biblio ou GMP ?


C'est notre bibliothèque MPFR.

j'ai toujours compris que MPFR se basait sur GMP (c'est ce que j'ai
compris d'une presentation de Guillaume).


Oui, et pour les allocations, on appelle les fonctions d'allocation de
GMP (qui peuvent être des appels à malloc ou autre chose). Ça pourrait
changer, ceci dit. Personnellement, je n'aime pas ces fonctions, qui
demandent notamment de fournir la taille des blocs qu'on veut libérer.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
espie
In article <20040109092333$,
Vincent Lefevre <vincent+ wrote:
Dans l'article <btkrhu$ms4$,
Marc Espie écrit:

In article ,
Erwan David wrote:
Euh, je ne vois pas ce qui pourrais provoquer ça. Les problèmes
d'ordre d'inclusion apparaissent quand a.h n'inclus pas b.h mais n'est
pas parsable sans l'avoir inclus (par exemple parceque a.h déclare une
fonction utilisant un type déclaré dans b.h)
Les entetes qui parfois ont des definitions supplementaires que tu n'as

pas prevues, et qui posent des problemes de portabilite parce qu'elles
collisionnent avec d'autres choses, et uniquement sur certains systemes.


Mais dans ce cas, on peut se retrouver avec des contraintes
insatisfiables. Maintenant, l'inclusion de <stdio.h> dans notre
fichier d'en-tete n'empêche pas son inclusion en tout début du
fichier .c, auquel cas il ne devrait pas y avoir de problème en
pratique.


Oui, on se retrouve parfois avec des contraintes insatisfiables.
Ca m'arrive assez regulierement, en fait. Comme je l'ai dit, il
suffit d'essayer de compiler des trucs pas trop portables sur d'autres
OS.

Et c'est plus facile a corriger si les entetes sont a plat que s'il
y a des inclusions multiples dans tous les sens.



Avatar
Erwan David
(Marc Espie) écrivait :

Oui, on se retrouve parfois avec des contraintes insatisfiables.
Ca m'arrive assez regulierement, en fait. Comme je l'ai dit, il
suffit d'essayer de compiler des trucs pas trop portables sur d'autres
OS.

Et c'est plus facile a corriger si les entetes sont a plat que s'il
y a des inclusions multiples dans tous les sens.


Mais je ne vois pas trop la différence pour tout remetrre à plat entre
des en-têtes spécifiquement inclus et des en-têtes non inclus, mais
nécessaires au parsing.

Avatar
espie
In article ,
Erwan David wrote:
(Marc Espie) écrivait :

Oui, on se retrouve parfois avec des contraintes insatisfiables.
Ca m'arrive assez regulierement, en fait. Comme je l'ai dit, il
suffit d'essayer de compiler des trucs pas trop portables sur d'autres
OS.

Et c'est plus facile a corriger si les entetes sont a plat que s'il
y a des inclusions multiples dans tous les sens.


Mais je ne vois pas trop la différence pour tout remetrre à plat entre
des en-têtes spécifiquement inclus et des en-têtes non inclus, mais
nécessaires au parsing.


C'est plus facile d'inserer des choses au bon endroit quand tu peux le
faire localement, que tu n'es pas oblige de le faire globalement dans le
fichier d'entetes qui inclut tout, mais que tu peux le faire dans le
fichier C qui a un probleme. L'air de rien, il n'est pas si frequent que
tu aies besoin de tout ce qu'il y a dans un fichier d'entetes donne sur
un fichier C en particulier. Par contre, sur un projet entier, tu peux avoir
besoin de toutes les fonctionnalites d'un fichier d'entetes.


Avatar
Erwan David
(Marc Espie) écrivait :

In article ,
Erwan David wrote:
(Marc Espie) écrivait :

Oui, on se retrouve parfois avec des contraintes insatisfiables.
Ca m'arrive assez regulierement, en fait. Comme je l'ai dit, il
suffit d'essayer de compiler des trucs pas trop portables sur d'autres
OS.

Et c'est plus facile a corriger si les entetes sont a plat que s'il
y a des inclusions multiples dans tous les sens.


Mais je ne vois pas trop la différence pour tout remetrre à plat entre
des en-têtes spécifiquement inclus et des en-têtes non inclus, mais
nécessaires au parsing.


C'est plus facile d'inserer des choses au bon endroit quand tu peux le
faire localement, que tu n'es pas oblige de le faire globalement dans le
fichier d'entetes qui inclut tout, mais que tu peux le faire dans le
fichier C qui a un probleme. L'air de rien, il n'est pas si frequent que
tu aies besoin de tout ce qu'il y a dans un fichier d'entetes donne sur
un fichier C en particulier. Par contre, sur un projet entier, tu peux avoir
besoin de toutes les fonctionnalites d'un fichier d'entetes.


Possible, mais d'un autre côté si un en-tête n'est pas parsable tout
seul il y a 9 chances sur 10 pour qu'un en-tête à inclure
obligatoirement avant ne soit pas documenté, ce qui rend l'utilisation
de ce module particulièrement malaisée pour quelqu'un qui ne le
connais pas parfaitement.



Avatar
Erwan David
(Marc Espie) écrivait :

In article ,
Erwan David wrote:
(Marc Espie) écrivait :

Oui, on se retrouve parfois avec des contraintes insatisfiables.
Ca m'arrive assez regulierement, en fait. Comme je l'ai dit, il
suffit d'essayer de compiler des trucs pas trop portables sur d'autres
OS.

Et c'est plus facile a corriger si les entetes sont a plat que s'il
y a des inclusions multiples dans tous les sens.


Mais je ne vois pas trop la différence pour tout remetrre à plat entre
des en-têtes spécifiquement inclus et des en-têtes non inclus, mais
nécessaires au parsing.


C'est plus facile d'inserer des choses au bon endroit quand tu peux le
faire localement, que tu n'es pas oblige de le faire globalement dans le
fichier d'entetes qui inclut tout, mais que tu peux le faire dans le
fichier C qui a un probleme.


Je ne comprends pas ton objection. Mon principe est que si le fichier
C utilise des notions (fonctions, variables, types, macros) de X ou Y
alors il inclus X.h et Y.h, mais que s'il n'utilise pas de notions de
Z alors il n'inclue pas Z.h, si X.h ou Y.h en ont besoin, alors ils
sont l'incluent eux même.

Ça me parait plus simple pour maintenir, que de devoir dans ton .c
inclure des en-têtes dont tu ne vois pas que tu les utilises.

L'air de rien, il n'est pas si frequent que tu aies besoin de tout
ce qu'il y a dans un fichier d'entetes donne sur un fichier C en
particulier. Par contre, sur un projet entier, tu peux avoir besoin
de toutes les fonctionnalites d'un fichier d'entetes.


Tout à fait, donc inclure A.h parcequ'une fonction de X.h en a besoin,
alors que je n'utilise pas cette fonction va à l'encontre de ce
principe.


D'un autre côté si un en-tête n'est pas parsable tout
seul il y a 9 chances sur 10 pour qu'un en-tête à inclure
obligatoirement avant ne soit pas documenté, ce qui rend l'utilisation
de ce module particulièrement malaisée pour quelqu'un qui ne le
connais pas parfaitement.



1 2 3 4 5