如何在C ++中的函数内声明一个extern C函数?

时间:2018-05-08 19:30:24

标签: c++ c

我有一个内联函数,大概是这样的:

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();
           ^

我该如何正确地做到这一点?

4 个答案:

答案 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();
}

信用转到stackoverflow上的这两个答案:herehere

答案 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 ++文件的一个级别上,它不能在较小的范围内(函数,块)。