Сделать функцию видимой только в библиотеке, а не в API
Я пишу библиотеку C99, которая распределена между несколькими файлами, например
// 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();
}
Я хочу только API_префиксом функции , чтобы быть видимыми с помощью программы , используя библиотеку, но я также необходимо выставить my_private_fnв core.hдля того , чтобы использоваться module_a.c. Есть ли способ в C сделать my_private_fnвидимым только в библиотеке?
Ответы
Если функция должна быть видна только в той единице компиляции, где она определена, вы можете объявить ее static. Поскольку язык C предлагает несколько возможных областей действия: символ может иметь только 3 области действия:
- локально для блока (блок может быть функцией или блоком внутри функции)
- статическая область видимости (статическое объявление вне функции): символ виден только в той единице компиляции, где он объявлен
- глобальная область видимости (нестатическое объявление вне функции): символ виден во всей программе.
В лучшем случае вы можете скрыть объявление в частном включаемом файле, который вы не объявляете в официальном документированном API. Таким образом, послушные пользователи не должны его использовать. Но вы не можете запретить пользователям помещать объявление в свой собственный код и использовать функцию.
Поместите их в внутренний файл заголовка , который используется только внутри библиотеки и не распространяется конечным пользователям, скажем, core_internal.h.
Я нашел более аккуратный способ изложить свой код, основанный на ответе Сержа, который я выбрал и которому принадлежит наибольшая заслуга.
Ключ состоит в том, чтобы поместить «частные» функции в заголовки, которые включаются только в файлы C, а не в файлы заголовков. Таким образом, «частные» символы доступны внутри, но не для внешнего вызывающего абонента. В полном примере:
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();
}
И если мы хотим, мы можем сгруппировать несколько модулей в общем заголовке библиотеки.
library.h:
#include "module_a.h"
// etc.
Таким образом, программа, использующая библиотеку, должна включать только один файл только с:
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;
}
Компиляция gcc -Wall *.c -o main.oи выполнение ./main.oкоманд:
Public function called.
Private function called.
Public function called.