C 使函数仅在库中可见,而不在API中可见
我正在编写一个分布在多个文件中的C99库,例如C 使函数仅在库中可见,而不在API中可见,c,visibility,C,Visibility,我正在编写一个分布在多个文件中的C99库,例如 // core.h void my_private_fn(); void API_my_public_fn(); 我只希望使用库的程序可以看到带前缀的函数,但我还需要在core.h中公开my_private\u fn,以便模块a.c使用。在C语言中有没有办法使my_private\u fn只在库中可见?将它们放在一个内部头文件中,该文件只在库中使用,不分发给最终用户,比如,core\u internal.h将它们放在一个内部头文件中,该头文件只
// core.h
void my_private_fn();
void API_my_public_fn();
我只希望使用库的程序可以看到带前缀的函数,但我还需要在
core.h
中公开my_private\u fn
,以便模块a.c
使用。在C语言中有没有办法使my_private\u fn
只在库中可见?将它们放在一个内部头文件中,该文件只在库中使用,不分发给最终用户,比如,core\u internal.h
将它们放在一个内部头文件中,该头文件只在库中使用,不分发给最终用户,比如说,core\u internal.h
如果函数必须只在定义它的编译单元中可见,那么您可以将其声明为static
。因为C语言提供的作用域很少:一个符号只能有3个作用域:
- 块的局部(块可以是函数或函数内部的块)
- 静态范围(函数外部的静态声明):符号仅在声明它的编译单元中可见
- 全局范围(函数外部的非静态声明):符号在整个程序中可见
最多,您可以将声明隐藏在一个私有的包含文件中,而不是在官方文档化的API中声明。这样顺从的用户就不应该使用它。但是您不能阻止用户将声明放在自己的代码中并使用该函数。如果该函数必须仅在定义它的编译单元中可见,则可以将其声明为
静态。因为C语言提供的作用域很少:一个符号只能有3个作用域:
- 块的局部(块可以是函数或函数内部的块)
- 静态范围(函数外部的静态声明):符号仅在声明它的编译单元中可见
- 全局范围(函数外部的非静态声明):符号在整个程序中可见
最多,您可以将声明隐藏在一个私有的包含文件中,而不是在官方文档化的API中声明。这样顺从的用户就不应该使用它。但是您不能阻止用户将声明放在自己的代码中并使用该函数。我找到了一种更简洁的方法,根据我选择的Serge的答案构建代码,其最大优点在于
关键是将“private”函数放在只包含在C文件中的头文件中,而不包含在头文件中。这样,“私有”符号在内部可用,但外部调用方无法使用。在完整的示例中:
core.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
core_priv.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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;
}
模块a.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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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;
}
如果需要,我们可以将多个模块分组到一个公共库头中
library.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
这样,使用库的程序只需包含一个文件,其中仅包含:
main.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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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.
我找到了一种更简洁的方式,在我选择的Serge答案的基础上构建代码,Serge的答案的最大优点在于
关键是将“private”函数放在只包含在C文件中的头文件中,而不包含在头文件中。这样,“私有”符号在内部可用,但外部调用方无法使用。在完整的示例中:
core.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
core_priv.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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;
}
模块a.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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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;
}
如果需要,我们可以将多个模块分组到一个公共库头中
library.h
:
void my_public_fn();
void my_private_fn();
#include "core.h"
void module_a_fn();
#include "module_a.h"
// etc.
这样,使用库的程序只需包含一个文件,其中仅包含:
main.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");
}
#include "core_priv.h"
#include "module_a.h"
void module_a_fn() {
my_private_fn();
my_public_fn();
}
#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.
根据您使用的平台,您可能会签出(注意,该问题的公认答案并不能解决您的问题)。您可能需要查看Windows及其\u declspec(dllimport)
和\u declspec(dllexport)
限定符,还可能需要查看GNU。取决于您使用的平台,您可以查看(请注意,该问题的公认答案并不能解决您的问题)。您可能需要查看Windows及其\uuudeclspec(dllimport)
和\uudeclspec(dllexport)
限定符,并且您可能需要查看GNU。我喜欢这个,因为它不需要特定于编译器的选项。我不关心流氓演员,只关心API的可读性。这比我建议的命名约定要好。谢谢。我喜欢这个,因为它不需要特定于编译器的选项。我不关心流氓演员,只关心API的可读性。这比我建议的命名约定要好。谢谢