Rendre la fonction visible uniquement dans une bibliothèque, pas dans l'API
J'écris une bibliothèque C99 qui est distribuée entre plusieurs fichiers, par exemple
// core.h
void my_private_fn();
void API_my_public_fn();
// core.c
#include "core.h"
void my_private_fn() {
do_something();
}
void API_my_public_fn() {
do_something_else();
}
// module_a.h
#include "core.h"
void API_useful_thing();
// module_a.c
#include "module_a.h"
void API_useful_thing() {
my_private_fn();
}
Je veux que les API_
fonctions préfixées soient visibles par un programme utilisant la bibliothèque, mais je dois aussi exposer my_private_fn
dans core.h
afin d'être utilisé par module_a.c
. Existe-t-il un moyen en C de my_private_fn
ne rendre visible que dans la bibliothèque?
Réponses
Si la fonction ne devait être visible que dans l'unité de compilation où elle est définie, vous pouvez la déclarer static
. Parce que le langage C offre peu de portées possibles: un symbole ne peut avoir que 3 portées:
- local à un bloc (le bloc peut être une fonction ou un bloc à l'intérieur d'une fonction)
- portée statique (déclaration statique en dehors d'une fonction): le symbole n'est visible que dans l'unité de compilation où il est déclaré
- portée globale (déclaration non statique en dehors d'une fonction): le symbole est visible dans tout le programme.
Tout au plus, vous pouvez masquer la déclaration dans un fichier d'inclusion privé que vous ne déclarez pas dans l'API documentée officielle. De cette façon, les utilisateurs obéissants ne devraient pas l'utiliser. Mais vous ne pouvez pas empêcher les utilisateurs de mettre la déclaration dans leur propre code et d'utiliser la fonction.
Placez-les dans un fichier d'en-tête interne qui n'est utilisé qu'à l'intérieur de la bibliothèque et non distribué aux utilisateurs finaux, par exemple core_internal.h
.
J'ai trouvé un moyen plus soigné de présenter mon code en me basant sur la réponse de Serge que j'ai choisie, dont le plus grand mérite revient.
La clé est de mettre les fonctions "privées" dans des en-têtes qui ne sont inclus que dans les fichiers C, pas dans les fichiers d'en-tête. De cette façon, les symboles «privés» sont disponibles en interne mais pas à un appelant externe. Dans un exemple complet:
core.h
:
void my_public_fn();
core_priv.h
:
void my_private_fn();
core.c
:
#include <stdio.h>
#include "core.h"
#include "core_priv.h"
void my_private_fn() {
printf("Private function called.\n");
}
void my_public_fn() {
printf("Public function called.\n");
}
module_a.h
:
#include "core.h"
void module_a_fn();
module_a.c
:
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
Et si nous le voulons, nous pouvons regrouper éventuellement plusieurs modules dans un en-tête de bibliothèque commun.
library.h
:
#include "module_a.h"
// etc.
De cette façon, un programme utilisant la bibliothèque n'a besoin d'inclure qu'un seul fichier avec seulement:
main.c
:
#include "library.h"
int main() {
//my_private_fn(); // This triggers a compile warning.
my_public_fn(); // I can still reach the "core" public function.
module_a_fn(); // This calls the "private" function internally.
return 0;
}
Compilation gcc -Wall *.c -o main.o
et exécution des ./main.o
rendements:
Public function called.
Private function called.
Public function called.