[英]extern “C”: What does and what doesn't need it?
关于函数的extern "C"
已经存在问题,但是这个问题试图将它扩展到其他事物,例如变量等等。
如果我有一个foo.hpp
头文件来使用C ++中的foo.c
文件,我制作了这个模板,我填写了这个问题的简单示例:
/******************************************************************************
******* 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 **********************************************************
******************************************************************************/
所有类型,宏, enum
, struct
, union
和extern
变量和函数应与C兼容(尽可能多)。 只有static
事物可以表现不同,因为我可以在标题中为C ++调整它们。
这是放置C包装器的正确位置吗?
虽然它也做其他事情,但关于extern "C"
要点是禁止名称修改 。
名称修改主要需要两件事:
由于所有全局(非命名空间)结构,枚举,类型和变量都不能重载,因此不需要名称修改,因此不需要extern "C"
。 它实际上只需要全局(非命名空间)功能。
extern "C"
声明函数类型,函数或变量以具有C语言链接[dcl.link] / 1 。 如果要在C ++代码中定义可用于C代码的函数或变量,或者如果要使C ++代码使用C代码中定义的函数或变量,则需要extern "C"
。 而已。 这基本上是所有C ++语言都要说的事情。
与流行的看法相反, extern "C"
目的不是禁止名称修改。 名称修改不是C ++语言中存在的概念,因此,不可能有一种方法可以在C ++语言中显式控制它。 名称修改是许多(基本上所有)C ++实现在将C ++代码映射到给定目标平台时使用的机制。 这是一个实现细节。 extern "C"
的目的是指示编译器做任何需要做的事情,以使给定的实体与目标平台上的C代码链接。 对于许多ABI,这意味着没有名称错误。 但是对于一些ABI,例如Windows ABI ,甚至C函数都受名称修改(在这种特殊情况下由于存在不同的调用约定)。 如果要将C ++代码与C代码链接,请使用extern "C"
。 这就是它的目的,这就是它的好处。 如果要控制导出或导入符号的名称,请根据给定目标平台的工具链文档使用任何方法,这通常是模块定义文件 ,链接器标志,...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.