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

Variable externe et bibliothèque dynamique.

9 réponses
Avatar
Zanner La Glauje
Bonjour,
Je veux utiliser une variable externe dans un programme pour qu'elle soit
utilisée par des fonctions appartenant à une bibliothèque dynamique.
Car j'ai déjà codé ces fonctions et elles sont assez nombreuses. Et je ne
veux pas leurs passer ma variable en paramètre car esthétisme de mon
programme en serait changé.
Comment dois-je déclarer ma variable dans mon programme et dans ma
bibliothèque et/ou son en-tête ?
Puis-je avoir l'assurance que plusieurs instances de mon programme en cours
d'exécution aient leur variable externe utilisée exclusivement des autres
par une bibliothèque dynamique unique en mémoire ?

ZannerLaGlauje.
Dans je sais tout il y a : Dans je sais il y a ... de trop:) ou seulement
ça.

9 réponses

Avatar
Harpo
On Sun, 15 Apr 2007 20:09:41 +0200, Zanner La Glauje wrote:

Bonjour,
Je veux utiliser une variable externe dans un programme pour qu'elle soit
utilisée par des fonctions appartenant à une bibliothèque dynamique.


C'est assez généralement une mauvaise idée, mais ça dépend.

Car j'ai déjà codé ces fonctions et elles sont assez nombreuses. Et je ne
veux pas leurs passer ma variable en paramètre car esthétisme de mon
programme en serait changé.
Comment dois-je déclarer ma variable dans mon programme et dans ma
bibliothèque et/ou son en-tête ?


Le problème est surtout que cette variable soit définie partout de la
même manière et de façon que changer le type de la variable ne
nécessite qu'une recompilation.
Pour la déclaration, je pense plutôt dans le programme, mais il faut
voir...

Puis-je avoir l'assurance que plusieurs instances de mon programme en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?


Je pense que c'est dépendant du système, mais dans le cas ou ces
instances sont dans des process séparés il n'y a pas de problème.

Enfin, je dis ça, on est la veille du lundi matin...

--
SKILL (Simple Knowledge Inference Logic Language)
http://patrick.davalan.free.fr/skill-0/

Avatar
Pascal Bourguignon
"Zanner La Glauje" writes:

Bonjour,
Je veux utiliser une variable externe dans un programme pour qu'elle soit
utilisée par des fonctions appartenant à une bibliothèque dynamique.
Car j'ai déjà codé ces fonctions et elles sont assez nombreuses. Et je ne
veux pas leurs passer ma variable en paramètre car esthétisme de mon
programme en serait changé.
Comment dois-je déclarer ma variable dans mon programme et dans ma
bibliothèque et/ou son en-tête ?


Le mieux, c'est de déclarer la variable dans la bibliothèque. Je ne
suis pas sur qu'une bibliothèque dynamique puisse se lier avec une
variable dans le programme qui la charge. (Mais voir ci-après).

Donc, on écrit:

--- biblio.h ----
extern mon_type ma_var;
extern mon_point_d_entree(...);
-----------------

--- biblio.c ----
mon_type ma_var;
mon_point_d_entree(...){
...
... ma_var ...
...
}
-----------------

On compile, on livre.


--- mon_pgm.c ---
#include <biblio.h>

int main(){
ma_var=quelque_chose();
mon_point_d_entree(...);
return(0);
}
-----------------

On compile, on exécute.


Voici le ci-après: Si on ne veut pas avoir la variable dans la
bibliothèque (par exemple, si on avait plusieurs bibliothèques devant
utiliser la même variable), on pourrait faire ceci:




--- biblio.h ----
extern mon_type* pointeur_sur_ma_var;
extern mon_point_d_entree(...);
-----------------

--- biblio.c ----
mon_type* pointeur_sur_ma_var=0;
initialiser(mon_type* ptr){
pointeur_sur_ma_var=ptr;
}
mon_point_d_entree(...){
...
... (*pointeur_sur_ma_var) ...
...
}
-----------------

On compile, on livre.


--- mon_pgm.c ---
#include <biblio.h>

mon_type* ma_var;
int main(){
ma_var=quelque_chose();
initialiser(&ma_var);
mon_point_d_entree(...);
return(0);
}
-----------------

On compile, on exécute.


C'est à dire qu'on s'est ramené au premier cas!



Puis-je avoir l'assurance que plusieurs instances de mon programme en cours
d'exécution aient leur variable externe utilisée exclusivement des autres
par une bibliothèque dynamique unique en mémoire ?


Si on a un système d'exploitation normal, avec séparation des espace
d'adressage par processus, oui. Tu ne travaille pas avec MS-DOS?


--
__Pascal Bourguignon__

Avatar
Antoine Leca
Zanner La Glauje wrote:
Je veux utiliser une variable externe dans un programme pour qu'elle
soit utilisée par des fonctions appartenant à une bibliothèque
dynamique.


En général c'est une mauvaise idée (sans parler du fait que l'idée même de
variable globale n'est pas vraiment une bonne idée en 2007). Les
bibliothèques dynamiques ont été inventées pour partager la mémoire (d'où le
nom anglais de /shared object/, objet partagé). Pas de problème pour
partager un objet invariant comme du code, mais c'est nettement moins
adaptées pour un objet qui peut être modifié comme le sont généralement les
variables.


Si en fait ta variable est une constante (elle ne varie donc pas au cours du
temps) et qu'il y a une seule bibliothèque dynamique partagée, il n'y a pas
de gros souci en perspective. Le plus simple (mais pas le plus beau) est de
remplacer

extern type ma_var;

par

extern type _cachemoi_ma_var(void);
#define ma_var (_cachemoi_ma_var())

et dans la bibliothèque dynamique écrire la fonction

/*globale*/ type ma_var_ici={0};
type _cachemoi_ma_var(void) { return ma_var_ici; }


Si tu veux une variable qui se modifie vraiment, ou plusieurs bibliothèques,
ou une constante dont la valeur dépend de chaque programme, c'est plus
coton, la manière de procéder dépend:
a) de l'implémentation des bibliothèques dynamiques sur ton système (en gros
il y a trois cas,
a.1- la solution "COFF/système V" qui ne te concerne probablement pas,
a.2- la solution Windows,
a.3- et la solution .so/SVR4 utilisée avec les *nix actuels),

b) et aussi cela dépend du choix que tu dois faire d'avoir ta variable:
b.1- unique par instance, donc chaque programme/processus qui se lie à la
bibliothèque voit une version différente de la variable; c'est ce qui se
passe pour errno, par exemple;
b.2- ou bien une variable partagée (et des joies en perspective pour la
synchronisation).


Puis-je avoir l'assurance que plusieurs instances de mon programme en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?


Oui (cf. supra, cas b-1). Mais ce n'est pas automatique (en général)... De
plus, au niveau des performances il y a un coût.


Antoine

Avatar
ZannerLaGlauje
test de réponse
Avatar
Pierre Maurette
test de réponse


Si vous ne voyez pas les réponses, vous pouvez consulter là:
<URL:http://groups.google.fr/group/fr.comp.lang.c/topics?lnk=gschg&hl=fr&gt;

--
Pierre Maurette

Avatar
ZannerLaGlauje
Bonjour,

Antoine Leca a écrit:

Zanner La Glauje wrote:

Je veux utiliser une variable externe dans un programme pour qu'elle
soit utilisée par des fonctions appartenant à une bibliothèque
dynamique.



En général c'est une mauvaise idée (sans parler du fait que l'idée même de
variable globale n'est pas vraiment une bonne idée en 2007). Les
bibliothèques dynamiques ont été inventées pour partager la mémoire (d'où le
nom anglais de /shared object/, objet partagé). Pas de problème pour
partager un objet invariant comme du code, mais c'est nettement moins
adaptées pour un objet qui peut être modifié comme le sont généralement les
variables.


Si en fait ta variable est une constante (elle ne varie donc pas au cours du
temps) et qu'il y a une seule bibliothèque dynamique partagée, il n'y a pas
de gros souci en perspective. Le plus simple (mais pas le plus beau) est de
remplacer

extern type ma_var;

par

extern type _cachemoi_ma_var(void);
#define ma_var (_cachemoi_ma_var())

et dans la bibliothèque dynamique écrire la fonction

/*globale*/ type ma_var_ici={0};
type _cachemoi_ma_var(void) { return ma_var_ici; }


Si tu veux une variable qui se modifie vraiment, ou plusieurs bibliothèques,
ou une constante dont la valeur dépend de chaque programme, c'est plus
coton, la manière de procéder dépend:
a) de l'implémentation des bibliothèques dynamiques sur ton système (en gros
il y a trois cas,
a.1- la solution "COFF/système V" qui ne te concerne probablement pas,
a.2- la solution Windows,


oui
une solution portable sur *nix actuels

a.3- et la solution .so/SVR4 utilisée avec les *nix actuels),

b) et aussi cela dépend du choix que tu dois faire d'avoir ta variable:
b.1- unique par instance, donc chaque programme/processus qui se lie à la
bibliothèque voit une version différente de la variable; c'est ce qui se
passe pour errno, par exemple;
oui errno est mon cas d'utilisation de ma variable partagée : un message

d'erreur propre au programme qui a fait appel à la fonction à l'origine
de l'erreur.

b.2- ou bien une variable partagée (et des joies en perspective pour la
synchronisation).



Puis-je avoir l'assurance que plusieurs instances de mon programme en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?



Oui (cf. supra, cas b-1). Mais ce n'est pas automatique (en général)... De
plus, au niveau des performances il y a un coût.
arhh... oui mais pas automatique (en général) ...hahaha

Comment puis-je le savoir sans tester ?



Antoine



La solution que j'ai retenu pour l'instant est :

---bibliotheque.h----
#include <stdlib>
void fnLibererErreurDuServeur();
void fnTestErreurDuServeur();
char *fnObtenirErreurDuServeur();
...
---------------------

---bibliotheque.c----
#include "bibliothèque.h"

char *errbuff=NULL;

/*fonctions permettant d'y accéder*/
void fnLibererErreurDuServeur()
{
free(errbuf);
errbuf=NULL;
}

void fnTestErreurDuServeur() {
errbuf="tralalalalalala";
}

char *fnObtenirErreurDuServeur() {
return errbuf;
}

/* et d'autres fonctions qui accèdent à errbuf comme
fnTestErreurDuServeur() en cas d'erreur par exemple d'un malloc ou
d'erreur à l'ouverture d'une base de données*/
...
---------------------

---programme.c-------
#include "bibliothèque.h"

int main() {
/* appel de fonctions de bibliotheque.c*/
if(fnObtenirErreurDuServeur()) {
/*j'ai un problème sur le serveur*/
}
return 0;
}
---------------------

bibliotheque.c est "compilé" pour être une bibliothèque dynamique.
Mais je ne sais pas si errbuff est unique pour chaque programme qui y
accède ou bien partagée par tout les programmes.
Comment obtenir les deux possibilités?

Ps : Merci, messieurs.

Cordialement,
ZannerLaGlauje,
"0=0 <=> 0=1 mille feuilles entamé + un toto qui a moins faim."


Avatar
ZannerLaGlauje
Bonjour,

Antoine Leca a écrit:

Zanner La Glauje wrote:

Je veux utiliser une variable externe dans un programme pour qu'elle
soit utilisée par des fonctions appartenant à une bibliothèque
dynamique.



En général c'est une mauvaise idée (sans parler du fait que l'idée même de
variable globale n'est pas vraiment une bonne idée en 2007). Les
bibliothèques dynamiques ont été inventées pour partager la mémoire (d'où le
nom anglais de /shared object/, objet partagé). Pas de problème pour
partager un objet invariant comme du code, mais c'est nettement moins
adaptées pour un objet qui peut être modifié comme le sont généralement les
variables.


Si en fait ta variable est une constante (elle ne varie donc pas au cours du
temps) et qu'il y a une seule bibliothèque dynamique partagée, il n'y a pas
de gros souci en perspective. Le plus simple (mais pas le plus beau) est de
remplacer

extern type ma_var;

par

extern type _cachemoi_ma_var(void);
#define ma_var (_cachemoi_ma_var())

et dans la bibliothèque dynamique écrire la fonction

/*globale*/ type ma_var_ici={0};
type _cachemoi_ma_var(void) { return ma_var_ici; }


Si tu veux une variable qui se modifie vraiment, ou plusieurs bibliothèques,
ou une constante dont la valeur dépend de chaque programme, c'est plus
coton, la manière de procéder dépend:
a) de l'implémentation des bibliothèques dynamiques sur ton système (en gros
il y a trois cas,
a.1- la solution "COFF/système V" qui ne te concerne probablement pas,
a.2- la solution Windows,


oui sur windows et également portable sur *nix actuels

a.3- et la solution .so/SVR4 utilisée avec les *nix actuels),

b) et aussi cela dépend du choix que tu dois faire d'avoir ta variable:
b.1- unique par instance, donc chaque programme/processus qui se lie à la
bibliothèque voit une version différente de la variable; c'est ce qui se
passe pour errno, par exemple;
oui errno est mon cas d'utilisation de ma variable partagée : un message

d'erreur propre au programme qui a fait appel à la fonction à l'origine
de l'erreur.

b.2- ou bien une variable partagée (et des joies en perspective pour la
synchronisation).



Puis-je avoir l'assurance que plusieurs instances de mon programme en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?



Oui (cf. supra, cas b-1). Mais ce n'est pas automatique (en général)... De
plus, au niveau des performances il y a un coût.
arhh... oui mais pas automatique (en général) ...hahaha

Comment puis-je le savoir sans tester ?



Antoine



La solution que j'ai retenu pour l'instant est :

---bibliotheque.h----
#include <stdlib>
void fnLibererErreurDuServeur();
void fnTestErreurDuServeur();
char *fnObtenirErreurDuServeur();
...
---------------------

---bibliotheque.c----
#include "bibliothèque.h"

char *errbuff=NULL;

/*fonctions permettant d'y accéder*/
void fnLibererErreurDuServeur()
{
free(errbuf);
errbuf=NULL;
}

void fnTestErreurDuServeur() {
errbuf="tralalalalalala";
}

char *fnObtenirErreurDuServeur() {
return errbuf;
}

/* et d'autres fonctions qui accèdent à errbuf comme
fnTestErreurDuServeur() en cas d'erreur par exemple d'un malloc ou
d'erreur à l'ouverture d'une base de données*/
...
---------------------

---programme.c-------
#include "bibliothèque.h"

int main() {
/* appel de fonctions de bibliotheque.c*/
if(fnObtenirErreurDuServeur()) {
/*j'ai un problème sur le serveur*/
}
return 0;
}
---------------------

bibliotheque.c est "compilé" pour être une bibliothèque dynamique.
Mais je ne sais pas si errbuff est unique pour chaque programme qui y
accède ou bien partagée par tout les programmes.
Comment obtenir les deux possibilités?

Ps : Merci, messieurs.

Cordialement,
ZannerLaGlauje,
"0=0 <=> 0=1 mille feuilles entamé + un toto qui a moins faim."


Avatar
ZannerLaGlauje
ZannerLaGlauje a écrit:

Bonjour,

Antoine Leca a écrit:

Zanner La Glauje wrote:

Je veux utiliser une variable externe dans un programme pour qu'elle
soit utilisée par des fonctions appartenant à une bibliothèque
dynamique.




En général c'est une mauvaise idée (sans parler du fait que l'idée
même de
variable globale n'est pas vraiment une bonne idée en 2007). Les
bibliothèques dynamiques ont été inventées pour partager la mémoire
(d'où le
nom anglais de /shared object/, objet partagé). Pas de problème pour
partager un objet invariant comme du code, mais c'est nettement moins
adaptées pour un objet qui peut être modifié comme le sont
généralement les
variables.


Si en fait ta variable est une constante (elle ne varie donc pas au
cours du
temps) et qu'il y a une seule bibliothèque dynamique partagée, il n'y
a pas
de gros souci en perspective. Le plus simple (mais pas le plus beau)
est de
remplacer

extern type ma_var;

par

extern type _cachemoi_ma_var(void);
#define ma_var (_cachemoi_ma_var())

et dans la bibliothèque dynamique écrire la fonction

/*globale*/ type ma_var_ici={0};
type _cachemoi_ma_var(void) { return ma_var_ici; }


Si tu veux une variable qui se modifie vraiment, ou plusieurs
bibliothèques,
ou une constante dont la valeur dépend de chaque programme, c'est plus
coton, la manière de procéder dépend:
a) de l'implémentation des bibliothèques dynamiques sur ton système
(en gros
il y a trois cas,
a.1- la solution "COFF/système V" qui ne te concerne probablement pas,
a.2- la solution Windows,



oui sur windows et également portable sur *nix actuels
Voir plus bas j'ai testé la solution Windows XP


a.3- et la solution .so/SVR4 utilisée avec les *nix actuels),

b) et aussi cela dépend du choix que tu dois faire d'avoir ta variable:
b.1- unique par instance, donc chaque programme/processus qui se lie
à la
bibliothèque voit une version différente de la variable; c'est ce qui se
passe pour errno, par exemple;


oui errno est mon cas d'utilisation de ma variable partagée : un message
d'erreur propre au programme qui a fait appel à la fonction à l'origine
de l'erreur.

b.2- ou bien une variable partagée (et des joies en perspective pour la
synchronisation).



Puis-je avoir l'assurance que plusieurs instances de mon programme en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?




Oui (cf. supra, cas b-1). Mais ce n'est pas automatique (en
général)... De
plus, au niveau des performances il y a un coût.


arhh... oui mais pas automatique (en général) ...hahaha
Comment puis-je le savoir sans tester ?



Antoine



La solution que j'ai retenu pour l'instant est :

---bibliotheque.h----
#include <stdlib>
void fnLibererErreurDuServeur();
void fnTestErreurDuServeur();
char *fnObtenirErreurDuServeur();
...
---------------------

---bibliotheque.c----
#include "bibliothèque.h"

char *errbuff=NULL;

/*fonctions permettant d'y accéder*/
void fnLibererErreurDuServeur()
{
free(errbuf);
errbuf=NULL;
}

void fnTestErreurDuServeur() {
errbuf="tralalalalalala";
}

char *fnObtenirErreurDuServeur() {
return errbuf;
}

/* et d'autres fonctions qui accèdent à errbuf comme
fnTestErreurDuServeur() en cas d'erreur par exemple d'un malloc ou
d'erreur à l'ouverture d'une base de données*/
...
---------------------

---programme.c-------
#include "bibliothèque.h"

int main() {
/* appel de fonctions de bibliotheque.c*/
if(fnObtenirErreurDuServeur()) {
/*j'ai un problème sur le serveur*/
}
return 0;
}
---------------------

bibliotheque.c est "compilé" pour être une bibliothèque dynamique.
Mais je ne sais pas si errbuff est unique pour chaque programme qui y
accède ou bien partagée par tout les programmes.
Comment obtenir les deux possibilités?
J'utilise Windows XP.

Par défaut, une variable globale (c-à-d définie hors fonction) dans une
bibliothèque partagée (c-à-d liée avec l'option -shared) est bien unique
pour chaque programme qui l'utilise (c-à-d que pour chaque couple
programme-bibliotèque la partie bibliothèque voit la variable globale
indépendemment des autres couples)

Par curiosité j'ai défini en static char *errbuff=NULL; mais je n'ai pas
obtenu ce que je souhaitais c-à-d une variable globale partagée par tout
les programme qui utilisent la bibliothèque qui définit la variable. En
effet je crois me rappeler que static ne s'utilise que dans une fonction .


Ps : Merci, messieurs.

Cordialement,
ZannerLaGlauje,
"0=0 <=> 0=1 mille feuilles entamé + un toto qui a moins faim."




Cordialement,
ZannerLaglauje,
"Pourquoi en français => but ou cause"



Avatar
Antoine Leca
ZannerLaGlauje wrote:

Antoine Leca a écrit:

Si tu veux une variable qui se modifie vraiment, ou plusieurs
bibliothèques, ou une constante dont la valeur dépend de chaque
programme, c'est plus coton, la manière de procéder dépend:
a) de l'implémentation des bibliothèques dynamiques sur ton système
(en gros il y a trois cas,
a.1- la solution "COFF/système V" qui ne te concerne probablement
pas,
a.2- la solution Windows,


oui sur windows et également portable sur *nix actuels

a.3- et la solution .so/SVR4 utilisée avec les *nix actuels),



Ce qu'il faut comprendre de ce que j'ai écrit, c'est qu'il y a des
différences substancielles entre l'implémentation Windows (héritée de
l'architecture COFF) et l'implémentation « classique *nix » (basée sur les
"objets partagés" ou .so, et utilisant en général le format ELF).

En gros, Windows a une solution plus « efficace » (plus rapide dans le cas
général) mais qui nécessite plus de soin dasn certains cas particuliers,
tandis que la solution .so est éloignée des contraintes, plus proche du
style de programmation classique avec des bibliothèques, au détriment des
performances.

Et l'un des cas où la différence est senseible, ce sont... les variables
partagées !


Puis-je avoir l'assurance que plusieurs instances de mon programme
en
cours d'exécution aient leur variable externe utilisée exclusivement
des autres par une bibliothèque dynamique unique en mémoire ?


Oui (cf. supra, cas b-1). Mais ce n'est pas automatique (en
général)... De plus, au niveau des performances il y a un coût.


arhh... oui mais pas automatique (en général) ...hahaha
Comment puis-je le savoir sans tester ?


Et comment pouvais-je savoir si tu visais Windows ou Linux ou *BSD ou que
sais-je ?



La solution que j'ai retenu pour l'instant est :
<couic>


En gros, si j'ai bien lu (en travers), tu as enrobé ta variable dans une
interface de programmation. Dans ce cas, il n'y a plus de souci de variable
partagée, c'est devenu un « objet » et on y accède avec des méthodes !


Mais je ne sais pas si errbuff est unique pour chaque programme qui y
accède ou bien partagée par tout les programmes.
Comment obtenir les deux possibilités?


Il faut contrôler l'instanciation (cela fait riche, mais en fait c'est une
tautologie ;-)). Historiquement, au début (avant 1995) le plus courant était
la seconde solution, aujourd'hui c'est très souvent la première (par
exemple, c'est une des différences importantes entre Win32 et Win16).

Pour GCC avec Windows, tu peux regarder du côté de
http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Variable-Attributes.html,
attribut "shared".

static (autorisé pour une variable globale) peut être une solution (selon
les implémentations, voire selon les versions), mais ne pas oublier que le
nom de la variable sera caché des autres fichiers sources (et donc, bien
sûr, ne sera pas partagé entre le programme et la bibliothèque ; cela
concerne le nom, pas la variable elle-même ; et on peut toujours accéder à
travers des pointeurs et une interface de programmation).

Bref, cela dépend de ton compilateur, tu va être obligé de lire la doc (et
de tester), et il y a des chances que le résultat ne soit guère portable
(surtout entre Windows et *nix :-< Et en avant les sections, mmap(),
VirtualAlloc et compagnie).


Antoine