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

Pointeur vers une fonction de classe static

32 réponses
Avatar
candide
Bonjour,

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?

En plus je vois pas comment c'est possible à moins d'utiliser une
variable globale.

Je pose la question car K.N. King évoque cette possibilité dans son
manuel de C et je voudrais savoir si ça a un quelconque intérêt et si ça
correspond à une pratique réelle.

[Je ne vois pas trop l'intérêt puisque si on définit une fonction en
classe statique c'est pour limiter son accès depuis un fichier externe à
sa définition et donc c'est circonvenir cette limitation d'accès que
d'utiliser un pointeur vers cette fonction.]


Si ma question n'est pas claire, je placerai ici l'extrait du livre de King.


Merci

10 réponses

1 2 3 4
Avatar
Mickaël Wolff
candide a écrit :
Bonjour,



Bonjour,

[Je ne vois pas trop l'intérêt puisque si on définit une fonction en
classe statique c'est pour limiter son accès depuis un fichier externe à
sa définition et donc c'est circonvenir cette limitation d'accès que
d'utiliser un pointeur vers cette fonction.]



Je vois bien un intérêt : réduire la maintenabilité de l'application :-D

Plus sérieusement, on peut imaginer utiliser cette propriété pour «
émuler » le système de classes de C++ dans C. C'est à dire que les
fonction static sont effectivement protégées, mais pour qu'on puisse
faire un héritage du module, il faut pouvoir accéder à ces « méthodes »
protégées.
On peut aussi imaginer utiliser cette propriété pour créer des
plugins, chargés dynamiquements, dont les fonctions ne sont accessibles
depuis l'extérieur que via des pointeurs contenus dans une structures.
Ça pourrait assurer le contournement des conflits de fonctions ayant le
même prototype (mais là je demandes confirmation).

Je suis sûr que ton imagination t'aidera comme elle vient de m'aider ;)
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Erwan David
candide écrivait :

Bonjour,

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?

En plus je vois pas comment c'est possible à moins d'utiliser une
variable globale.

Je pose la question car K.N. King évoque cette possibilité dans son
manuel de C et je voudrais savoir si ça a un quelconque intérêt et si
ça correspond à une pratique réelle.



J'ai déjà vu faire, pour un file system embarqué sur flash :
à l'initialisation on rmepli une structure avec des adresses de
fonctions statiques de bas niveau pour la flash (écrire, lire effacer un bloc)
et la lib de file system appelle les fonctions via les champs de cette
structure.


--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
espie
In article <488f4a6e$0$7251$,
candide wrote:
Bonjour,

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?

En plus je vois pas comment c'est possible à moins d'utiliser une
variable globale.



Facile: en utilisant autre chose de global.

Par exemple, une fonction non-statique.

Je te laisse mediter sur la chose suivante:
un fichier C qui ne contient QUE des definitions d'objets statiques n'a
pas grande utilite. tu es oblige de communiquer avec le reste du monde
par des trucs globaux, que ce soit des fonctions ou des variables.

Une bonne part du design des gros projets, c'est precisement de limiter
les interactions entre les diverses composants a un petit nombre
d'interfaces judicieusement definies.

Tu peux par exemple avoir une fonction globale qui te remplit une structure
(pointeur passe en parametre) avec les pointeurs sur les fonctions
statiques dont nous parlons.

Ca marche tres bien, ca ne reduit absolument pas la maintenabilite de
l'application, bien au contraire... Ca permet de n'exposer qu'un seul
nom public, et d'avoir les autres noms de fonctions locales au fichier C,
donc t'as meme pas besoin d'avoir de conventions de nommage pour eviter
les collisions avec le reste du monde.
Avatar
Thierry B.
--{ candide a plopé ceci: }--

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?



Pourrais-tu proposer un exemple minimum, svp ? Parce que ça me
parait un peu tordu... Il faudrait que le code de a.c appelle
une fonction du fichier b.c pour obtenir l'adresse de f...


--
# find / -type f -uid 0 -perm -u=sx -exec chmod u-s {} ;
Après ça plein de choses vont très très mal marcher... Mais comme ton système
a déjà de gros problèmes entre son clavier et sa chaise, ce n'est pas trop
grave. --{ YBM, répondant à Ptilou dans fcol.configuration }--
Avatar
Thierry B.
--{ Thierry B. a plopé ceci: }--

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?



Pourrais-tu proposer un exemple minimum, svp ? Parce que ça me
parait un peu tordu... Il faudrait que le code de a.c appelle
une fonction du fichier b.c pour obtenir l'adresse de f...



C'est bon, j'ai lu l'exemple donné par Marc Espie, et en fait
ça me donne quelques idées... Merci d'avoir lancé ce fil :)



--
====== /------------------------------------------ ===== | http://la.buvette.org/POV/ex/grille.html |
====== ------------------------------------------/ ======
Avatar
Wykaaa
Marc Espie a écrit :
In article <488f4a6e$0$7251$,
candide wrote:
Bonjour,

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?

En plus je vois pas comment c'est possible à moins d'utiliser une
variable globale.



Facile: en utilisant autre chose de global.

Par exemple, une fonction non-statique.

Je te laisse mediter sur la chose suivante:
un fichier C qui ne contient QUE des definitions d'objets statiques n'a
pas grande utilite. tu es oblige de communiquer avec le reste du monde
par des trucs globaux, que ce soit des fonctions ou des variables.

Une bonne part du design des gros projets, c'est precisement de limiter
les interactions entre les diverses composants a un petit nombre
d'interfaces judicieusement definies.

Tu peux par exemple avoir une fonction globale qui te remplit une structure
(pointeur passe en parametre) avec les pointeurs sur les fonctions
statiques dont nous parlons.

Ca marche tres bien, ca ne reduit absolument pas la maintenabilite de
l'application, bien au contraire... Ca permet de n'exposer qu'un seul
nom public, et d'avoir les autres noms de fonctions locales au fichier C,
donc t'as meme pas besoin d'avoir de conventions de nommage pour eviter
les collisions avec le reste du monde.



C'est même tout à fait comme ça qu'il faut faire pour respecter
l'encapsulation et donc augmenter la maintenabilité.
En plus, c'est une sorte de "programmation objet" en C.

Merci à toi, Marc, qui a très bien expliqué la construction.
Avatar
Côme Desplats
Thierry B. wrote:
--{ Thierry B. a plopé ceci: }--

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?


Pourrais-tu proposer un exemple minimum, svp ? Parce que ça me
parait un peu tordu... Il faudrait que le code de a.c appelle
une fonction du fichier b.c pour obtenir l'adresse de f...



C'est bon, j'ai lu l'exemple donné par Marc Espie, et en fait
ça me donne quelques idées... Merci d'avoir lancé ce fil :)



Voici une doc qui peut aussi donner quelques idées d'implémentation :
http://chgi.developpez.com/c/objet/
Avatar
candide
Merci de vos réponses.

Effectivement, la variable globale que je suggérais d'utiliser n'est pas
nécessaire.

J'ai trouvé assez peu de doc sur la question mais dans celle que j'ai
trouvée, l'idée de la structure contenant les adresses des fonctions
static et qu'on initialise revient le plus souvent.

Voici deux liens vers clc :

*) filesystem schématique :
http://groups.google.fr/group/comp.lang.c/msg/17cfaff5e330cd2c?hl=fr


*) interface modulaire :
http://groups.google.fr/group/comp.lang.c/msg/4a21413e25458439?hl=fr
Avatar
Jean-Marc Desperrier
candide wrote:
[...]
J'ai trouvé assez peu de doc sur la question mais dans celle que j'ai
trouvée, l'idée de la structure contenant les adresses des fonctions
static et qu'on initialise revient le plus souvent.
[...]



Pour un exemple industriel, c'est le modèle qu'utilise l'interface
PKCS#11 v2 :
http://www.rsa.com/rsalabs/node.asp?id!33
Avatar
FrihD
candide wrote:
Bonjour,



Bonjour,

Avez-vous déjà rencontré du code qui appelle depuis un fichier a.c une
fonction g qui prend en argument l'adresse d'une fonction f définie
static dans un autre fichier b.c ?



Oui, mais tu n'utiliseras pas le symbole de la fonction f dans le
fichier a.c .
En gros, tu peux trouver g(f) dans b.c mais pas dans a.c .

[...]
Je pose la question car K.N. King évoque cette possibilité dans son
manuel de C et je voudrais savoir si ça a un quelconque intérêt et si ça
correspond à une pratique réelle.
[Je ne vois pas trop l'intérêt puisque si on définit une fonction en
classe statique c'est pour limiter son accès depuis un fichier externe à
sa définition et donc c'est circonvenir cette limitation d'accès que
d'utiliser un pointeur vers cette fonction.]


Ça permet de faire une librairie partagée qui définit des prototypes de
base pour des fonctions à appeler. L'important c'est d'avoir le
prototype pour éviter d'exploser la pile d'appels, et de définir le
comportement attendu de la fonction dans un header.

L'intérêt c'est le même que pour une fonction static "non appellée par
pointeur" : moins de symboles, moins de risques de conflits de noms,
code plus simple à appréhender.

Par exemple, tu peux implémenter un algorithme de tri qui prend en
premier paramètre une fonction de comparaison qui elle même prend deux
paramètres. L'utilisateur de la librairie n'aura pas à se soucier de
l'algorithme, mais seulement de la comparaison, ça rejoint le concept
"interface" de la POO.

Par exemple, tu peux faire:
typedef int (*fonction_de_comparaison)(void*,void*);
et ta tri_par_bulle prendra alors une liste d'élèments et la
fonction_de_comparaison. De la même manière qu'il faut établir une
convention pour la fonction de comparaison (par exemple le set 2 1 3 5
avec la fonction "supérieur" donne 1 2 3 5 et non pas 5 3 2 1), il faut
établir une convention sur la représentation de la liste d'élèments à
trier (un tableau de pointeurs par exemple), et sur celle une fois triée.

Pour l'utilisation ? outre faire de l'objet en C, c'est utilisé partout
dès que tu as des appels à des entrées/sorties asynchrones, la Glib
utilise ça lors des "g_io_add_watch", POSIX lorsque tu rajoute un
"handler" via la fonction signal etc.

L'avantage: ça permet de s'abstraire de beaucoup de choses et de faire
du code très modulaire. L'inconvénient: c'est très probable qu'un
utilisateur se trompe de types à un moment ou à un autre car avec mon
exemple précédent, la commande suivante passera inaperçue à la compilation:
trier_par_bulle( &compare_torchons, (void*) liste_serviettes )
même si on est incapable de trier une liste de serviettes avec une
fonction sur les torchons.
Au mieux t'as une segfault, au pire t'as un résultat faux dans certains
cas vicieux qui n'arrivent qu'en production (typiquement veux comparer
des entiers signés, passe un non signé et tu testes que sur des cas "qui
marchent").

Merci


De rien ;) j'espère avoir été utile.

--Lucas
1 2 3 4