是否可以使用 C11 原子包含 C 标头而无需在C++中进行修改?

Is it possible to include a C header using C11 atomics without modification in C++?

本文关键字:C++ 修改 C11 可以使 包含 是否      更新时间:2023-10-16

我正在尝试编写使用此 C 库而不在C++应用程序中进行修改。它使用C11原子学。

考虑以下程序,我们可以将其放入一个名为main.cc.

#include "mpscq.h"

int main(){}

如果我用g++ -std=c++11 -c main.cc编译它,我会得到一大堆错误,如下所示。

usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdatomic.h:68:9: error: ‘_Atomic’ does not name a type
typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t;
^
/usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdatomic.h:69:9: error: ‘_Atomic’ does not name a type
typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t;

是否可以在不修改库代码的情况下修复这些错误?

也就是说,我愿意在我的 c++ 代码或编译器标志中使用任何需要的魔法咒语,但我宁愿不更改库代码。

我已经看到了这个答案,但它需要修改头文件。

是否可以在不修改库代码的情况下修复这些错误?

C++ 没有_Atomic类型限定符,但在库标头中声明的结构具有具有_Atomic限定类型的成员(包括第一个(。 C++不会接受这一点(将标头包含在extern "C"块中将无济于事(。

C 允许限定类型的对象_Atomic与同一类型的非_Atomic版本的对象具有不同的表示形式,因此在一般意义上,这意味着C++不能直接访问该结构的任何实例的任何成员。

如果您的 C 实现碰巧对相应的_Atomic和非_Atomic类型使用相同的表示形式,那么您可能会通过将符号_Atomic#define为空字符串来使 C++ 编译器接受标头,但这将是通往更微妙错误的门户。 您不能期望C++提供库期望的原子访问语义,因此即使在这种情况下,C++也无法安全地访问结构的成员(直接(。

如果仅通过提供的函数操作struct的实例就足够了,则可以通过不透明指针进行操作。 创建一个标头版本,该版本提供结构的前向声明,但没有定义,并提供所有函数声明(带 C 链接(。 C++代码应该接受标头并能够调用函数,接收和返回指向它绝不能尝试取消引用的结构实例的指针。

#ifndef __MPSCQ_H
#define __MPSCQ_H
#ifdef __cplusplus
extern "C" {
#endif
struct mpscq;
struct mpscq *mpscq_create(struct mpscq *n, size_t capacity);
// other functions ...
#ifdef __cplusplus
}
#endif
#endif

如果您需要的函数超过现有函数提供的功能,则需要在 C 中编写其他帮助程序函数。

你不需要包装器来C++代码中使用该mpscq,但你需要不同的 标头以包含它。那会起作用:

#ifndef MPSCQ_H_FOR_CPP
#define MPSCQ_H_FOR_CPP
extern "C"
{
struct mpscq;
mpscq *mpscq_create(mpscq *n, size_t capacity);
bool mpscq_enqueue(mpscq *q, void *obj);
void *mpscq_dequeue(mpscq *q);
size_t mpscq_count(mpscq *q);
size_t mpscq_capacity(mpscq *q);
void mpscq_destroy(mpscq *q);
}
#endif

也就是说,无论如何我都会写一个包装器来处理 RAII 等。