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

时间:2018-08-16 18:54:37

标签: c++ c atomic c11

我试图在C ++应用程序中使用this C library 未经修改进行编写。它使用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 ++代码或编译器标志中需要的任何魔术,但我不想更改库代码。

我见过this answer,但它需要修改头文件。

2 个答案:

答案 0 :(得分:5)

您不需要在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之类的东西。

答案 1 :(得分:4)

  

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

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

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

如果您的C实现碰巧对相应的_Atomic和非_Atomic类型使用相同的表示形式,则可以通过#define设置符号来使C ++编译器接受标头_Atomic到一个空字符串,但这将是通往更多细微错误的门户。您不能期望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编写其他辅助功能。