Сделать функцию видимой только в библиотеке, а не в API

Nov 29 2020

Я пишу библиотеку 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видимым только в библиотеке?

Ответы

3 SergeBallesta Nov 29 2020 at 01:39

Если функция должна быть видна только в той единице компиляции, где она определена, вы можете объявить ее static. Поскольку язык C предлагает несколько возможных областей действия: символ может иметь только 3 области действия:

  • локально для блока (блок может быть функцией или блоком внутри функции)
  • статическая область видимости (статическое объявление вне функции): символ виден только в той единице компиляции, где он объявлен
  • глобальная область видимости (нестатическое объявление вне функции): символ виден во всей программе.

В лучшем случае вы можете скрыть объявление в частном включаемом файле, который вы не объявляете в официальном документированном API. Таким образом, послушные пользователи не должны его использовать. Но вы не можете запретить пользователям помещать объявление в свой собственный код и использовать функцию.

2 JohnKugelman Nov 29 2020 at 01:35

Поместите их в внутренний файл заголовка , который используется только внутри библиотеки и не распространяется конечным пользователям, скажем, core_internal.h.

user3758232 Dec 31 2020 at 00:19

Я нашел более аккуратный способ изложить свой код, основанный на ответе Сержа, который я выбрал и которому принадлежит наибольшая заслуга.

Ключ состоит в том, чтобы поместить «частные» функции в заголовки, которые включаются только в файлы 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.