繁体   English   中英

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

[英]How to declare an extern C function inside a function in 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();
           ^

我怎样才能正确地做到这一点?

extern "C"是一个链接规范 C++ 标准第7.5链接规范第 4 段指出:

链接规范应仅出现在命名空间范围 (3.3) 中。

例如,您可以在全局名称空间或某些特定名称空间中说extern "C" 在命名空间之外,这是非法的。

尽管在较小的范围内,函数声明是可能的。 如果您删除链接规范,您的代码将编译(但不是链接):

inline void SomeFunction() {
    extern void SomeOtherFunction();
    SomeOtherFunction();
}

如果您确实需要在较小范围内的SomeOtherFunction声明(例如从全局范围隐藏),您可以将您的声明放入一个专用范围的头文件中,然后在您的函数中使用:

标题:

namespace other {
    extern "C" void SomeOtherFunction();
}//namespace other

代码:

void SomeFunction()
{
    other::SomeOtherFunction();
}

归功于 stackoverflow 上的这两个答案: herehere

来自 C++11 标准(在[dcl.link] 中,重点是我的):

4 连杆规格嵌套。 当链接规范嵌套时,最里面的一个确定语言链接。 链接规范不建立范围。 链接规范应仅出现在命名空间范围内

链接规范指的是extern string-literal ... ,即extern "C"在您的情况下。)

这意味着您不能在类或函数中使用extern "C"

SomeFunction中声明SomeOtherFunction有什么意义? 它仍然必须是一个全局符号并且对链接器可见。

那么为什么不这样做呢?

#ifdef __cplusplus
    extern "C" 
#endif
void SomeOtherFunction();

inline void SomeFunction() {
    SomeOtherFunction();
}

以下似乎也有效:

extern "C" {
    inline void SomeFunction() {
        extern void SomeOtherFunction();
        SomeOtherFunction();
    }    
}

但是它会产生副作用,使SomeFunction也使用 C 链接(希望可以,因为(根据您的要求)它也需要从 C 中可用)。

你可以这样做。 我假设您有一个头文件、一个 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 上检查,它编译。

extern告诉编译器在其他模块中定义了一个符号(函数、变量)。 编译此模块(C++ 文件)时,目标文件包含它需要的外部符号列表。 所以这是在 C++ 文件的级别上,它不能在更小的范围内(函数、块)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM