如何在C代码中模拟c++名称空间特性
How can one emulate the C++ namespace feature in a C code?
我正在开发一个软件,这是在c++中,但通过包含通信协议的共享头文件与C应用程序通信。由于C比c++"更基本",我总是需要用C代码编写头文件(因此c++也得到了它);否则,它将无法在第二个应用程序中工作。
问题是我需要使用作用域限定符,如c++ namespace
s -这在C中不存在。
在C中模拟namespace
特性的所有选项是什么?
struct
s来完成这项工作,但没有成功(至少考虑到enum
操作器的struct
)。
您可以在定义级别使用static
隐藏从模块导出的所有导出函数,这样全局空间中就不会放置任何名称,而是将它们放在模块唯一提供的结构体中。
。foo:
struct ns_t {
int (*a)(int, int);
void (*b)(float, float);
};
extern struct ns_t ns;
foo.c:
#include "foo.h"
static int a(int x, int y) {
...
}
static void b(float x, float y) {
...
}
struct ns_t ns = { .a = a, .b = b };
bar.c:
#include "foo.h"
....
ns.b(4.5, 6.8);
....
完全不要模仿C中的命名空间,用C的方式:
- 使用前缀代替命名空间 使用后缀代替重载。
- 可以选择使用
_Generic
宏来模拟参数类型的重载。
你的include文件应该在c++的内部细节命名空间中定义这些C函数(由于C链接,不改变函数的实际身份),然后你从c++的C函数中去掉前缀和后缀。
它看起来像这样:
#ifndef MY_HEADER_GUARD_unique_suffix
#define MY_HEADER_GUARD_unique_suffix
#ifdef __cplusplus
namespace my_module {
namespace detail {
extern "C" {
#endif
// Defines for common structs and functions here
// Also inline functions written in the common intersection of C and C++
#ifdef __cplusplus
}
}
using init = detail::my_module_init;
using close = detail::my_module_close;
}
#endif
#endif
您可能还希望在某些C结构中为c++接口添加成员函数,这些成员函数可能是委托给共享函数的内联函数。
首先,用名称空间为所有导出的符号(包括预处理器定义和枚举成员的名称)加上前缀。例如,可以有一个函数声明
void foo_bar_baz(void);
在c++端,这些需要在extern "C" { … }
中包装,然后应该用正确的命名空间注册。假设使用c++ 11,对于函数,这应该像
namespace foo {
namespace bar {
constexpr auto baz = foo_bar_baz;
}
}
在C端,您可以定义像
这样的缩写名#define baz foo_bar_baz
使用特定于编译器的属性来注册别名或添加常量声明
static void (*const baz)(void) = foo_bar_baz;
这样做很好,因为调用函数实际上使用了函数指针(而不是指示符)。
你可以把所有的东西放在一个单独的头文件中,适当的#ifdef
,或者你可以提供一个小的包装器,比如foo/bar.hxx
(c++)和foo/bar-import.h
(缩短的C名称),除了foo/bar.h
(包含实际的前缀声明,将包括在其他头文件中)。
我一直在研究一个非常依赖于名称空间(即构建类型插入的名称空间)的系统,从我对C的观察来看,您可以不完美地模拟C++
名称空间(无论如何在Linux上),方法是收集您导出的用于静态链接的符号,用objcopy
作为前缀,然后宏翻译您的头代码(不包括包含)以匹配前缀符号集。
这样做的问题是宏不尊重作用域,所以假设你的库导出void foo()
(或简称符号foo
) -并且你将其前缀为mylib_foo
,那么将foo
转换为mylib_foo
的宏也会不加区分地翻译名为foo
的结构体成员,即使这些成员不应该被翻译。
我相信做正确的事情实际上需要破解编译器(请有人来做!):))。
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- OpenGL相机和相机空间转型的困惑
- CUDA内核和数学函数的显式命名空间
- 打印第二列时的2d字符矢量打印空间
- 嵌套的匿名命名空间
- CMakeLists.txt中的命名空间表示法
- 类是C++中的命名空间吗
- 在命名空间中使用全局命名空间中的函数
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 为什么 openmp 的并行不适用于矢量化色彩空间转换?
- 是否可以将函数导入命名空间,但不能导出它?
- C++ C++类中的命名空间降级