2

已经有extern "C"关于函数的问题,但是这个问题试图将其扩展到其他事物,例如变量等等。

如果我有一个foo.hpp使用foo.cC++ 文件的标头,我制作了这个模板,并为这个问题填充了简单的示例:

/******************************************************************************
 ******* include guard { ******************************************************
 ******************************************************************************/
#ifndef FOO_HPP
#define FOO_HPP


/******************************************************************************
 ******* headers **************************************************************
 ******************************************************************************/
#include <cstdbool>
#include <cstddef>
#include <cstdint>


/******************************************************************************
 ******* typedefs *************************************************************
 ******************************************************************************/
/* `#if !defined(UINT128_MAX)` is to test if uint128_t already exists */
#if !defined(UINT128_MAX)
    typedef __uint128_t uint128_t;
    typedef __int128_t  int128_t;
#endif


/******************************************************************************
 ******* macros ***************************************************************
 ******************************************************************************/
#if !defined(UINT128_MAX)
    #define UINT128_MAX (~((uint128_t)0))
#endif
#if !defined(INT128_MAX)
    #define INT128_MAX  ((int128_t)(UINT128_MAX >> 1))
#endif
#if !defined(INT128_MIN)
    #define INT128_MIN  ((int128_t)(-INT128_MAX - 1))
#endif


/******************************************************************************
 ******* enums ****************************************************************
 ******************************************************************************/
enum    Some_Enum {
    SOME_CONSTANT_A,
    SOME_CONSTANT_B,

    SOME_CONSTANT_C
};


/******************************************************************************
 ******* structs / unions *****************************************************
 ******************************************************************************/
union   Some_Union {
    int128_t    a;
    int64_t     b[SOME_CONSTANT_C];
};

struct  Some_Struct {
    union Some_Union    a;
    bool                b;
};


/******************************************************************************
 ******* static const variables ***********************************************
 ******************************************************************************/
static const    struct Some_Struct  x = {
    .a  = {
        .b  = {
            [SOME_CONSTANT_A]   = 0,
            [SOME_CONSTANT_B]   = 1
        }
    },
    .b  = true
};


/******************************************************************************
 ******* C wrapper { **********************************************************
 ******************************************************************************/
extern  "C" {


/******************************************************************************
 ******* extern variables *****************************************************
 ******************************************************************************/
extern  union Some_Union    y;


/******************************************************************************
 ******* extern functions *****************************************************
 ******************************************************************************/
int foo(size_t n, int128_t arr[restrict]);


/******************************************************************************
 ******* } C wrapper **********************************************************
 ******************************************************************************/
}   /* extern "C" */


/******************************************************************************
 ******* static inline functions (prototypes) *********************************
 ******************************************************************************/
static inline   int compare_ldbl(const void *a_p, const void *b_p);


/******************************************************************************
 ******* static inline functions (definitions) ********************************
 ******************************************************************************/
static inline   int compare_ldbl(const void *a_p, const void *b_p)
{
    long double a = *(long double *)a_p;
    long double b = *(long double *)b_p;

    if (a < b)
        return  -1;
    else if (a > b)
        return  1;
    else
        return  0;
}


/******************************************************************************
 ******* } include guard ******************************************************
 ******************************************************************************/
#endif      /* foo.hpp */


/******************************************************************************
 ******* end of file **********************************************************
 ******************************************************************************/

所有类型、宏、enums、structs、unions 以及extern变量和函数都应该与 C 兼容(尽可能)。只有static事情可以表现不同,因为我可以在标题中为 C++ 调整它们。

那是放置 C 包装器的正确位置吗?

4

2 回答 2

6

虽然它也做其他事情,但主要的一点extern "C"是要抑制name mangling

名称修改主要用于两件事:

  1. 函数重载
  2. 允许在不同范围内具有相同名称的符号

由于所有全局(非命名空间)结构、枚举、类型和变量都不能重载,因此它们不需要名称修改,因此不需要extern "C". 它实际上只需要全局(非命名空间)函数。

于 2019-03-15T13:34:27.570 回答
2

extern "C"将函数类型、函数或变量声明为具有 C 语言链接[dcl.link]/1。如果您extern "C"想让 C++ 代码中定义的函数或变量可用于 C 代码,或者如果您想让 C++ 代码使用 C 代码中定义的函数或变量,则需要。就是这样。这基本上是 C++ 语言对此事的全部看法。

与流行的看法相反,目的extern "C" 不是为了抑制名称篡改。名称修饰不是 C++ 语言中存在的概念,因此,不可能有一种方法可以从 C++ 语言中显式控制它。名称修饰是许多(基本上所有)C++ 实现在将您的 C++ 代码映射到给定目标平台时采用的一种机制。这是一个实现细节。的目的extern "C"是指示编译器执行任何需要执行的操作,以使给定实体与目标平台上的 C 代码链接。对于许多 ABI,这意味着没有名称修改。但是对于某些 ABI,例如Windows ABI,甚至 C 函数也会受到名称修改(在这种特殊情况下,由于存在不同的调用约定)。extern "C"当您想将 C++ 代码与 C 代码链接时使用。这就是它的目的,这就是它的全部好处。如果您想控制导出或导入符号的名称,请根据给定目标平台的工具链文档使用任何方法,这通常是模块定义文件、链接器标志等内容……</ p>

于 2019-03-15T14:14:34.520 回答