Clean C++: 正确使用extern "C"的姿势

extern "C"用于明确告诉C++编译器放弃名字粉碎的工作机制,使其保留原始的符号名称。

纯粹的C库

即使你提供的是一个纯粹的C库,也必须正确使用extern "C",因为你的C函数可能被C++的程序所使用。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#include "oss_common.h"

#ifdef  __cplusplus
extern "C" {
#endif

void* oss_alloc(size_t);
void  oss_free(void*);

#ifdef  __cplusplus
}
#endif

#endif

如果在C库中遗漏extern "C"的声明,则C++程序员为了引用该库的符号时,唯一的选择就是使用extern "C"包含整个头文件,而这种模式恰好是一种反模式。因此,C程序员定义对外公开的头文件时,需要特别的注意这件事情。

#ifdef  __cplusplus
extern "C" {
#endif

#include "oss_memory.h"

#ifdef  __cplusplus
}
#endif

反模式

extern "C"中包含头文件,是一种典型的反模式。如下示例代码,oss_common.h置于extern "C"之中,将导致其内部或间接通过#include引入的符号都置于extern "C"的作用域之内;更为严重的是,如果oss_common.h也使用了extern "C",将导致嵌套的extern "C"语句,导致混乱的符号声明。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#ifdef  __cplusplus
extern "C" {
#endif

#include "oss_common.h"

void* oss_alloc(size_t);
void  oss_free(void*);

#ifdef  __cplusplus
}
#endif

#endif

实用宏

可以定义一组实用宏,简化extern "C"的作用域定义。在代码的可读性没有下降的前提下,代码从6行减少至2行。

// cub/base/externc.h
#ifdef __cplusplus
# define EXTERN_STDC_BEGIN extern "C" {
# define EXTERN_STDC_END }
#else
# define EXTERN_STDC_BEGIN
# define EXTERN_STDC_END
#endif

例如,上例使用宏定义后的代码如下所示。

// oss/include/oss_memery.h
#ifndef HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8
#define HF0916DFB_1CD1_4811_B82B_9B8EB1A007D8

#include "cub/base/externc.h"
#include "oss_common.h"

EXTERN_STDC_BEGIN

void* oss_alloc(size_t);
void  oss_free(void*);

EXTERN_STDC_END

#endif

猜你喜欢

转载自blog.csdn.net/weixin_33857230/article/details/90959636