如何在C中实现在C++命名空间中声明的函数
How can I implement in C a function declared in a C++ namespace?
假设我有一个C++头文件foo.hpp
:
namespace foo {
int bar(int);
}
我不能使用extern "C"
,因为它只需要从命名空间foo
访问。
是否有一种可移植(或相对可移植)的方法可以在C文件foo.c
中声明foo::bar
,以便它与使用C++中的foo::bar
的任何人链接?
我知道,在一个具有特定编译器的特定系统上,我可以发现foo::bar
是如何被破坏的,并在foo.c
:中执行类似的操作
int ZN3foo3barEi(int x) { /* ... */ }
但这既不可移植,也不可读。
extern "C"
可以嵌套(事实上,像<cstdio>
这样的头文件通常就是这样工作的!),所以您只需执行以下操作:
/* C++ code */
namespace foo {
extern "C" {
int bar(int);
}
}
之后,您只需像往常一样在C中实现它:
/* C code */
int bar(int x) {
return -x; /* or whatever */
}
不幸的是,如果存在命名冲突(例如,如果您同时拥有foo::bar
和baz::bar
),您将无法同时拥有它们,除非它们是相同的函数。
包装器可以接受吗?
namespace foo {
int bar(int);
}
extern "C" int callable_from_c(int f) {
return foo::bar(f);
}
您被迫执行备份计划(使用包装函数),原因如下:C++支持函数重载,因此,bar
可以有不同的实现(具有不同的指纹,甚至是兼容的),而在C中只能有一个实现。如果从C调用bar
,C++的哪些可能性会匹配?如果您在C++中有bar(int)
和bar(long)
,并且您想从C调用bar(3)
,该怎么办?
解决方案是使用一个包装器extern "C"
函数来调用相应的非C函数。这个函数可以从C调用,你会得到想要的结果。
例如,如果您查看链接器管理的标识符名称,您将看到编译器如何在链接时篡改标识符以应对重载。如果在C++中声明函数extern "C"
,则不会发生这种情况。
另一个原因是C中没有命名空间。C函数版本必须在全局命名空间级别可见。您不能在命名空间中隐藏C调用约定,因为它可以从所有C代码中调用,否则将违反C调用约定。
- C++:为什么允许在另一个函数中声明函数,而不允许在函数定义中声明?
- 在c++中在类外声明函数有什么好处
- 使用 #define 声明函数
- 在静态库中声明函数,在使用该相同库的应用程序中定义它
- 如何强制编译器在 C/C++ 本身中声明函数?
- 如果您只需要在 .h 文件中声明函数.cpp是否需要在 .h 文件中声明函数?
- C++:<sys/sysctl.h> 无法声明函数CTL_HW和HW_NCPU
- 尝试声明函数的局部变量,但得到范围错误
- 如何在C++模板中声明函数
- 如何在另一个文件的类中声明函数
- 使用非类型模板参数正向声明函数模板
- 在此范围错误中未声明函数错误
- 当我们不能声明函数内联(GCC 编译器)时?
- 未在此作用域中声明函数,即使存在头文件也是如此
- 无法声明函数中的模板类型别名
- 单个CPP文件中多次声明函数声明可以吗?
- 编译一个支持VBA中声明函数的dll
- 使用从外部参数包中获取的参数类型声明函数
- 使用类成员正确地声明函数
- 在函数内重新声明函数