Pokaż funkcję tylko w bibliotece, a nie w API
Piszę bibliotekę C99 która jest rozprowadzana na kilka plików np
// 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();
}
Chcę tylko API_
funkcje poprzedzone być widoczny przez program przy użyciu biblioteki, ale również muszą wystawiać my_private_fn
na core.h
w celu wykorzystania przez module_a.c
. Czy w C jest sposób, aby były my_private_fn
widoczne tylko w bibliotece?
Odpowiedzi
Gdyby funkcja miała być widoczna tylko w jednostce kompilacji, w której została zdefiniowana, można by ją zadeklarować static
. Ponieważ język C oferuje kilka możliwych zakresów: symbol może mieć tylko 3 zakresy:
- lokalny dla bloku (blok może być funkcją lub blokiem wewnątrz funkcji)
- zakres statyczny (deklaracja statyczna poza funkcją): symbol jest widoczny tylko w jednostce kompilacji, w której jest zadeklarowany
- zasięg globalny (niestatyczna deklaracja poza funkcją): symbol jest widoczny w całym programie.
Możesz co najwyżej ukryć deklarację w prywatnym pliku dołączanym, którego nie zadeklarujesz w oficjalnie udokumentowanym interfejsie API. W ten sposób posłuszni użytkownicy nie powinni go używać. Nie można jednak uniemożliwić użytkownikom umieszczania deklaracji w ich własnym kodzie i używania funkcji.
Umieść je w wewnętrznym pliku nagłówkowym, który jest używany tylko w bibliotece i nie jest rozprowadzany do użytkowników końcowych - powiedzmy core_internal.h
.
Znalazłem zgrabniejszy sposób na rozplanowanie mojego kodu w oparciu o odpowiedź Serge'a, którą wybrałem, a która ma największą wartość.
Kluczem jest umieszczenie funkcji „prywatnych” w nagłówkach, które są zawarte tylko w plikach C, a nie w plikach nagłówkowych. W ten sposób symbole „prywatne” są dostępne wewnętrznie, ale nie dla rozmówcy zewnętrznego. W pełnym przykładzie:
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();
}
A jeśli chcemy, możemy zgrupować wiele modułów we wspólnym nagłówku biblioteki.
library.h
:
#include "module_a.h"
// etc.
W ten sposób program korzystający z biblioteki musi zawierać tylko jeden plik zawierający tylko:
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;
}
Kompilowanie gcc -Wall *.c -o main.o
i wykonywanie wyników ./main.o
:
Public function called.
Private function called.
Public function called.