简体   繁体   English

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

[英]How to declare an extern C function inside a function in C++?

I have an inline function, roughly like this:我有一个内联函数,大致是这样的:

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

This is a simplification: my functions do have parameters and return values.这是一个简化:我的函数确实有参数和返回值。

However, I want this header to work in both C and C++ files.但是,我希望这个头文件在 C 和 C++ 文件中都可以使用。 Currently, linking fails because C++ files attempt to find an implementation of SomeOtherFunction with C++ linkage.目前,链接失败是因为 C++ 文件尝试使用 C++ 链接查找SomeOtherFunction的实现。 I thought I could just fix this by using extern "C" :我以为我可以通过使用extern "C"来解决这个问题:

inline void SomeFunction() {
#ifdef __cplusplus
    extern "C" void SomeOtherFunction();
#else
    extern void SomeOtherFunction();
#endif
    SomeOtherFunction();
}

This causes Clang to fail with:这会导致 Clang 失败:

error: expected unqualified-id
    extern "C" void SomeOtherFunction();
           ^

How can I do this correctly?我怎样才能正确地做到这一点?

extern "C" is a linkage-specification . extern "C"是一个链接规范 C++ standard section 7.5 Linkage specifications paragraph 4 states that: C++ 标准第7.5链接规范第 4 段指出:

A linkage-specification shall occur only in namespace scope (3.3).链接规范应仅出现在命名空间范围 (3.3) 中。

Eg you can say extern "C" in global namespace or some specific namespace.例如,您可以在全局名称空间或某些特定名称空间中说extern "C" Outside of namespaces it is illegal.在命名空间之外,这是非法的。

Function declarations are possible though in smaller scopes.尽管在较小的范围内,函数声明是可能的。 If you remove linkage specification your code will compile (but not link):如果您删除链接规范,您的代码将编译(但不是链接):

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

If you really need SomeOtherFunction declaration in a smaller scope (eg hide from global scope) you can put your declaration into a header file to a dedicated scope and then use in your function:如果您确实需要在较小范围内的SomeOtherFunction声明(例如从全局范围隐藏),您可以将您的声明放入一个专用范围的头文件中,然后在您的函数中使用:

Header:标题:

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

Code:代码:

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

Credit goes to these two answers on stackoverflow: here and here .归功于 stackoverflow 上的这两个答案: herehere

From the C++11 standard (in [dcl.link] , emphasis mine):来自 C++11 标准(在[dcl.link] 中,重点是我的):

4 Linkage specifications nest. 4 连杆规格嵌套。 When linkage specifications nest, the innermost one determines the language linkage.当链接规范嵌套时,最里面的一个确定语言链接。 A linkage specification does not establish a scope.链接规范不建立范围。 A linkage-specification shall occur only in namespace scope .链接规范应仅出现在命名空间范围内

( linkage-specification refers to extern string-literal ... , ie extern "C" in your case.) 链接规范指的是extern string-literal ... ,即extern "C"在您的情况下。)

This means you can't have extern "C" inside of a class or function.这意味着您不能在类或函数中使用extern "C"

What's the point of declaring SomeOtherFunction inside of SomeFunction ?SomeFunction中声明SomeOtherFunction有什么意义? It still has to be a global symbol and visible to the linker.它仍然必须是一个全局符号并且对链接器可见。

So why not do this?那么为什么不这样做呢?

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

inline void SomeFunction() {
    SomeOtherFunction();
}

The following also seems to work:以下似乎也有效:

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

But it would have the side effect of making SomeFunction also use C linkage (which is hopefully OK as (per your requirements) it needs to be usable from C, too).但是它会产生副作用,使SomeFunction也使用 C 链接(希望可以,因为(根据您的要求)它也需要从 C 中可用)。

You can do this like that.你可以这样做。 I assume you have a header file, a C source and a C++ source.我假设您有一个头文件、一个 C 源代码和一个 C++ 源代码。

Header file:头文件:

inline void SomeFunction()
{
    void SomeOtherFunction_Bridge();
    SomeOtherFunction_Bridge();
}

C++ source: C++ 源代码:

extern "C" 
{
    void SomeOtherFunction();
}

void SomeOtherFunction_Bridge()
{
    SomeOtherFunction();
}

C source: C源:

void SomeOtherFunction()
{
    // Function with a code doing something
}

void SomeOtherFunction_Bridge()
{
    SomeOtherFunction();
}

Checked on GCC, it compiles.在 GCC 上检查,它编译。

extern tells the compiler that a symbol (function, variable) is defined in some other module. extern告诉编译器在其他模块中定义了一个符号(函数、变量)。 When this module (C++ file) is compiled, object file contains a list of external symbols it needs.编译此模块(C++ 文件)时,目标文件包含它需要的外部符号列表。 So this is on a level of a C++ file, it cannot be in smaller scope (function, block).所以这是在 C++ 文件的级别上,它不能在更小的范围内(函数、块)。

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

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