2017-09-05 19 views
2

Supposons que j'ai une bibliothèque foo qui se compose des modules foo et util et a l'arbre source suivante:Hiding symboles non-API dans la bibliothèque

foo/ 
    foo.c 
    foo.h 
    util.c 
    util.h 

L'API publique de la bibliothèque est défini dans foo.h et tous les identificateurs globaux sont correctement préfixés par foo_ ou util_. Le module util est uniquement utilisé par foo. Pour éviter les conflits de noms avec d'autres modules nommés util Je souhaite créer une bibliothèque (statique) dans laquelle seuls les identificateurs du module foo sont visibles. Comment puis-je faire ceci? Edit: J'ai beaucoup cherché sur internet mais étonnamment cela semble être l'un de ces problèmes non résolus en informatique.

Répondre

0

Avant chaque déclaration variable et fonction dans util.h, définir une macro constante qui renomme l'identifiant déclaré en ajoutant le préfixe de la bibliothèque foo_, par exemple

#define util_x foo_util_x 
extern int util_x; 

#define util_f foo_util_f 
void util_f(void); 

... 

Avec ces définitions en place, pas d'autres parties du code doivent être modifiés, et tous les symboles globaux dans le fichier objet util.o seront préfixés avec foo_. Cela signifie que les collisions de noms sont moins susceptibles de se produire.

2

Il y a probablement d'autres approches possibles, mais en voici une:

Vous pourriez envisager d'inclure le fichier util.c au sein foo.c et de faire toutes les fonctions util/GLOBALS statique. i.e. .:

#include "util.c" 
// ... 

Cela fonctionne comme *.h fichiers, il ports simplement toute source dans foo.c, l'imbrication util.c et de faire toutes les données statiques disponibles.

Quand je fais cela, je Renommez le fichier .inc (c.-à-util.c =>util.inc) ...

#include "util.inc" 
// ... 

... c'est une convention plus j'ai pris quelque part, mais il pourrait entrer en conflit avec l'assembleur fichiers, vous devrez donc utiliser votre propre discrétion.

EDIT

Une autre approche pourrait nécessiter des directives spécifiques de liaison. Par exemple, this SO answer details GNU's ld to achieve this goal. Il existe également d'autres approches, répertoriées dans ce même fil.

+0

C'est une approche intéressante. Cependant, je préférerais une solution qui fonctionne au niveau du fichier objet. –

+0

@AugustKarlstrom Je peux définitivement comprendre cette préférence. Cependant, je pense que ce serait une solution spécifique aux liens. J'ai édité ma réponse avec des détails. – Myst

+0

L'approche GNU ld à laquelle vous êtes lié requiert la gestion manuelle d'un fichier de symboles exportés. Je devrais pouvoir dire que tous les symboles dans util.o devraient être cachés. –

0

Ce qui suit est spécifique à GCC.

Vous pouvez marquer chaque fonction d'utilité avec

__attribute__((visibility ("hidden"))) 

qui l'empêchera d'être lié à un autre objet partagé.

Vous pouvez l'appliquer à une série de déclarations en les entourant de

#pragma GCC visibility push(hidden) 
/* ... */ 
#pragma GCC visibility pop 

ou utiliser -fvisibility=hidden lors de la compilation de l'objet, qui applique aux déclarations sans visibilité explicite (par exemple ni __attribute__((visibility)) ni #pragma GCC visibility).