我有一个内联函数,大概是这样的:
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
这是一个简化:我的函数确实有参数和返回值。
但是,我希望此标头在C和C ++文件中都能正常工作。目前,链接失败,因为C ++文件尝试使用C ++链接查找SomeOtherFunction
的实现。我想我可以通过使用extern "C"
:
inline void SomeFunction() {
#ifdef __cplusplus
extern "C" void SomeOtherFunction();
#else
extern void SomeOtherFunction();
#endif
SomeOtherFunction();
}
这会导致Clang失败:
error: expected unqualified-id
extern "C" void SomeOtherFunction();
^
我该如何正确地做到这一点?
答案 0 :(得分:3)
extern "C"
是一个链接规范。 C ++标准部分 7.5链接规范 paragraph 4表明:
linkage-specification 只能在命名空间范围(3.3)中出现。
E.g。你可以在全局命名空间或某个特定命名空间中说extern "C"
。在命名空间之外,这是非法的。
虽然在较小的范围内可以进行函数声明。如果删除链接规范,则代码将编译(但不链接):
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
如果您确实需要在较小范围内进行SomeOtherFunction
声明(例如,隐藏全局范围),您可以将声明放入头文件中,然后在您的函数中使用:
部首:
namespace other {
extern "C" void SomeOtherFunction();
}//namespace other
代码:
void SomeFunction()
{
other::SomeOtherFunction();
}
答案 1 :(得分:2)
从C ++ 11标准([dcl.link],强调我的):
4链接规范嵌套。当链接规范嵌套时,最里面的规则确定语言链接。链接规范不会建立范围。 链接规范只能在命名空间范围内发生。
( linkage-specification 指的是extern string-literal ...
,即你的extern "C"
。)
这意味着您不能在类或函数中使用extern "C"
。
在SomeOtherFunction
内声明SomeFunction
有什么意义?它仍然必须是一个全局符号,并且链接器可见。
那么为什么不这样做?
#ifdef __cplusplus
extern "C"
#endif
void SomeOtherFunction();
inline void SomeFunction() {
SomeOtherFunction();
}
以下似乎也有效:
extern "C" {
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
}
但它会产生副作用,使SomeFunction
也使用C链接(希望可以(根据您的要求)它也可以从C中使用)。
答案 2 :(得分:0)
你可以这样做。我假设你有一个头文件,一个C源代码和一个C ++源代码。
标题文件:
inline void SomeFunction()
{
void SomeOtherFunction_Bridge();
SomeOtherFunction_Bridge();
}
C ++来源:
extern "C"
{
void SomeOtherFunction();
}
void SomeOtherFunction_Bridge()
{
SomeOtherFunction();
}
C来源:
void SomeOtherFunction()
{
// Function with a code doing something
}
void SomeOtherFunction_Bridge()
{
SomeOtherFunction();
}
检查GCC,它编译。
答案 3 :(得分:-3)
extern
告诉编译器在某个其他模块中定义了一个符号(函数,变量)。编译此模块(C ++文件)时,目标文件包含所需的外部符号列表。所以这是在C ++文件的一个级别上,它不能在较小的范围内(函数,块)。