C 中的命名空间
有没有办法(ab)使用C预处理器来模拟C中的命名空间?
我正在思考这样的事情:
#define NAMESPACE name_of_ns
some_function() {
some_other_function();
}
这将被翻译为:
name_of_ns_some_function() {
name_of_ns_some_other_function();
}
Is there a way to (ab)use the C preprocessor to emulate namespaces in C?
I'm thinking something along these lines:
#define NAMESPACE name_of_ns
some_function() {
some_other_function();
}
This would get translated to:
name_of_ns_some_function() {
name_of_ns_some_other_function();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
您可以使用 ## 运算符:
并将函数声明为:
不过看起来很尴尬。
You could use the ## operator:
and declare functions as:
Looks pretty awkward though.
我使用基于结构的方法,并进行了两项改进:添加子结构来创建分层命名空间,并在想要简化命名空间的路径时定义一些简单的宏。
让我们以 Foobar 库为例。
foobar.h
foobar.c
然后,就可以使用命名空间了:
但是
foobar_text__print()
和之间没有太大区别>foobar.text.print()
。 我认为第二个更具可读性,但值得怀疑。 因此,通过定义一些宏来简化这些命名空间变得非常有用:这种分层命名空间定义速度快,易于理解,并减少了代码的冗长。
只是为了好玩,这里是
foobar.text
代码的文件:foobar_text.h
foobar_text.c
I use the struct-based approach, with two refinements: I add substructures to create hierarchical namespaces, and I define some simple macros when I want to simplify namespaces' path.
Let's take a Foobar library as an example.
foobar.h
foobar.c
Then, it's possible to use the namespace:
But there is not so much difference between
foobar_text__print()
andfoobar.text.print()
. I think the second one is more readable, but it's questionable. So it become really useful by defining some macros to simplify these namespaces:This kind of hierarchical namespaces is fast to define, easy to understand, and decrease code verbosity.
Just for fun, here are the files for
foobar.text
code:foobar_text.h
foobar_text.c
我想出了以下方案:(
标题)
(实现)
I came up with the following scheme :
(header)
(implementation)
我写了一篇关于如何使用 C 来利用命名空间和/或模板的教程。
C 中的命名空间和模板
C 中的命名空间和模板(使用链接列表)
对于基本命名空间,可以简单地为命名空间名称添加前缀作为约定。
可以写为
使用命名空间和模板概念的第二种方法是使用宏串联和包含。 例如,我可以创建一个
使用模板文件,如下所示:
multiply-template.h、
multiply-template.c
我们现在可以如下定义 int_multiply。 在此示例中,我将创建一个 int_multiply.h/.c 文件。
int_multiply.h
int_multiply.c
在这一切结束时,您将拥有一个函数和头文件。
我根据提供的链接创建了一个更详细的教程。 希望这对某人有帮助!
I wrote up a tutorial on how to get the advantage of namespaces and/or templates using C.
Namespaces and templates in C
Namespaces and templates in C (using Linked Lists)
For the basic namespace, one can simply prefix the namespace name as a convention.
can be written as
A second approach that I have needed that uses the concept of namespacing and templates is to use the macro concatenation and include. For example, I can create a
using template files as follows
multiply-template.h
multiply-template.c
We can now define int_multiply as follows. In this example, I'll create a int_multiply.h/.c file.
int_multiply.h
int_multiply.c
At the end of all of this, you will have a function and header file for.
I created a much more detailed tutorial on the links provided. Hopefully this helps someone!
与接受的答案类似的方法如下:
此头文件应附带一个 .c 文件:
使用函数时,
An approach similar to the accepted answer is the following:
this header file shall come with a .c file:
when using the functions,
您可以使用辅助
#define
宏:通过预处理器运行它可以得到:
You can use a helper
#define
macro:Running it through the preprocessor gives you:
可以使用文件函数名称的前缀,例如 stb 用于 C/C++ 的单文件公共域库 :“作为命名文件名和源函数名称的一种适度合理的方式”。
示例:
One can use prefixes for file function names, like in stb single-file public domain libraries for C/C++: "as a moderately sane way of namespacing the filenames and source function name".
Examples:
这是一个基于上述方法并将它们组合起来的函数和结构的示例,以创建伪命名空间 NAMESPACE1 和 NAMESPACE2。 与拥有保存函数的结构相比,这种方法的好处在于,结构保存函数方法需要跨多个伪命名空间的标准化结构,而这并不总是可能的(要么根本不可能,要么不需要做大量的工作)不改进代码)还是可取的。
不确定宏扩展顺序是否可能是一个问题,但这适用于 GCC,并且似乎最大限度地减少了所需的代码更改量,同时保持良好的(尽管远非理想)可读性。
application.c:
header1.h
api1.c:
header2.h和api2.c中的其他代码与header1.h和header2.h相同,针对命名空间“NAMESPACE2”进行修改
here is an example that builds off above approaches and combines them for both funcs and structures to create pseudo-namespaces NAMESPACE1 and NAMESPACE2. the benefit of this over having a structure that holds functions is that the structure-holding-functions approach requires a standardized structure across multiple pseudo-namespaces, and this is not always possible (either at all, or without a lot of work that arguably does not improve the code) or desirable.
Not sure if the macro expansion order could be an issue but this works on GCC and seems to minimize the amount of code changes required, while maintaining decent (though far from ideal) readability.
application.c:
header1.h
api1.c:
Other code in header2.h and api2.c is the same as header1.h and header2.h, modified for namespace "NAMESPACE2"
我意识到这是一个老问题(11年前),但我试图基本上完成我认为你最初想要的事情,正如你上面列出的那样。
我希望在我的函数前面有一个名称空间。 但我希望能够更改该命名空间。 默认情况下,我希望此示例没有名称空间,但如果发生命名冲突,那么我希望能够在库中的所有函数前面添加名称空间。 (与 C++ 相比,这稍微落后了一点,C++ 默认有一个命名空间,并且您可以使用
using namespace another
来消除每次都指定命名空间的需要。)但是,就像 C++ 一样,如果您添加using namespace
语句并为您的代码添加别名,您将需要更新您的调用代码。 您也可以编写一些其他宏序列来自动重命名您的调用,但这超出了我认为您正在寻找的范围。此代码只能在 C99 及更高版本上编译,因为它使用可变参数宏。 这些宏执行一种递归形式,这一切都是为了我们可以从顶部定义的宏中获取值。
其工作原理分解:
这段代码是用 clang 测试的。
I realize that this is an old question (11 years old), but I was trying to accomplish essentially what I think you wanted originally as you have listed above.
I wanted there to be a namespace prepended to my functions. But I wanted the ability to change what that namespace would be. By default I wanted for this example to not have a namespace, but if a naming collision occurred then I wanted the ability to prepend a namespace to all of the functions in my library. (This is slightly backwards compared to C++ where there is a namespace by default and you use
using namespace whatever
to remove the need to specify the namespace every time.) However, just like C++ if you drop in ausing namespace
statement and alias your code, you will need to update your calling code. You could write some other macro sequence to auto rename your calls as well, but that is outside the scope of what I think you were looking for.This code will compile only on C99 and up since it is using variadic macros. These macros do a form of recursion which is all done so that we can grab the value out of a macro defined at the top.
Breakdown of all it works:
This code was tested with clang.
另一种选择是声明一个结构体来保存所有函数,然后静态定义函数。 那么您只需要担心全局名称结构的名称冲突。
在上面的例子中,
my_bar
和my_baz
不能直接从main.c调用,只能通过foo
调用。如果您有一堆声明具有相同签名的函数的命名空间,那么您可以标准化
该集合的命名空间结构,并选择在运行时使用哪个命名空间。
my_bar
和my_baz
的多个定义不会冲突,因为它们是静态定义的,但仍然可以通过适当的命名空间结构访问底层函数。Another alternative would be to declare a struct to hold all your functions, and then define your functions statically. Then you'd only have to worry about name conflicts for the global name struct.
In the above example,
my_bar
andmy_baz
can't be called directly from main.c, only throughfoo
.If you have a bunch of namespaces that declare functions with the same signatures, then you can standardize
your namespace struct for that set, and choose which namespace to use at runtime.
The multiple definitions of
my_bar
andmy_baz
don't conflict, since they're defined statically, but the underlying functions are still accessible through the appropriate namespace struct.使用命名空间前缀时,我通常会为缩短的名称添加宏,这些宏可以在包含标头之前通过#define NAMESPACE_SHORT_NAMES 激活。 标头 foobar.h 可能如下所示:
如果我想在包含文件中使用短名称,我会
发现这是比使用 Vinko Vrsalovic(在评论中)描述的命名空间宏更干净、更有用的解决方案。
When using namespace prefixes, I normally add macros for the shortened names which can be activated via
#define NAMESPACE_SHORT_NAMES
before inclusion of the header. A header foobar.h might look like this:If I want to use short names in an including file, I'll do
I find this a cleaner and more useful solution than using namespace macros as described by Vinko Vrsalovic (in the comments).