为什么某些C项目(例如nginx和LuaJIT)在其所有代码文件,函数和数据类型前加上项目名称?

时间:2018-07-01 10:46:31

标签: c coding-style

查看nginx的代码,我发现几乎所有内容都以ngx_为前缀。

文件:

ngx_list.c
ngx_list.h
ngx_log.c
ngx_log.h

代码:

ngx_log_t *ngx_log_init(u_char *prefix);
void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);

LuaJIT与lj_几乎相同。

文件:

lj_alloc.c
lj_alloc.h
lj_api.c
lj_arch.h

代码:

LJ_ASMF void LJ_FASTCALL lj_vm_ffi_call(CCallState *cc);
LJ_FUNC CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o);
LJ_FUNC int lj_ccall_func(lua_State *L, GCcdata *cd);

其他项目也做同样的事情,这些只是我想到的两个。他们为什么这样做呢?如果它是项目的公共API,那么我会得到它,因为它将暴露给第三方代码。但是我复制的代码是(私有)实现的一部分,那么为什么要为其命名空间?

1 个答案:

答案 0 :(得分:3)

我怀疑没有坚定的理由。我怀疑这只是人们(某些人)感到更舒服的事情。我本人不会这样做,但我想我可以看到这种吸引力。

例如,有一个我为娱乐而编写的多精度算术库。它具有mp_add()mt_sub()等功能。这些功能的源代码位于文件add.csub.c中。

现在,由于该库的所有源代码都位于名为mp的子目录中,所以我从来没有想过要给文件名提供诸如mp_add.cmp_sub.c之类的文件。那将是多余的:名称已经是非常真实的mp/add.cmp/sub.c等。

但是我不得不承认,进入名为add.c的文件来检查我的 multiprecision 附加代码确实有点古怪。它不是整数加法码,也不是定点或有理数加法码,也不是通用加法码。这是非常精确的多精度加法代码,并且其中定义的函数都具有mp_前缀。那么文件名也应该不带有该前缀吗?

正如我所说,不,最后我不会(我没有)给它加上前缀。但是正如我也说的,我想我可以看到这种吸引力。


附录:以上我回答了有关文件名的问题,但您还询问了内部(“私有”)函数的名称。这些是不同的;至少在C中肯定需要前缀。

问题在于 C确实没有任何名称空间机制。因此,几乎总是必须在所有全局符号上使用项目特定的前缀来伪造它。

考虑功能ngx_log_abort()。它对nginx是私有的;客户端代码不会调用它。但这是一个全局函数,因此如果仅将其命名为log_abort,则在客户端代码(或某些其他库代码)中也有一个完全不同的函数(也称为{{ 1}}。

您可能会问,为什么log_abort是全局函数?当然,答案是组成nginx库的任何函数都可能需要调用它,因此它几乎必须是全局的。

您可能会问,为什么ngx_log_abort不是文件作用域ngx_log_abort的功能?答案是,如果整个nginx库的所有源代码都限制在一个C源文件static中,那将是可行的。但是作者可能不想那样限制自己。

如果您想用C编写一个封装良好的库,则您的“私有”函数有两种选择:

  1. 使它们成为文件范围nginx.c,并限制您对大多数或所有库使用单个源文件。

  2. 使它们真正具有全局性,但具有唯一的前缀。也不要在公共头文件中放置它们的声明。 (这样客户就不能不作弊就打电话给他们。)

在其他语言中,您还有其他用于隐藏专用符号的机制,但在C语言中则没有。