C vs C++ несовместимость компиляции - не называет тип

Я пытаюсь использовать библиотеку поставщика в сочетании с моим C++ приложением. Библиотека в основном основана на C, что обычно не является проблемой с опцией extern "C", но я столкнулся с проблемой, которую компилятор C++ не принимает.

Я упростил свой код в следующих файлах примеров. header.h представляет собой заголовок из библиотеки suppier, main.c/cpp - мои собственные файлы. Мое реальное приложение - это приложение C++, поэтому я хочу заставить его работать с main.cpp.

header.h (обратите внимание на строку u64 u64;):

#ifndef HEADER_H
#define HEADER_H

#include <stdint.h>

typedef uint64_t u64;

union teststruct {
    u64 u64;
    struct {
        u64 x:32;
        u64 y:32;
    } s;
};

#endif

main.c:

#include <stdio.h>
#include "header.h"

int main() {
    union teststruct a;
    a.u64=5;
    printf("%x\n", a.u64);

    return 0;
}

main.cpp (то же, что и main.c, но с дополнительным extern "C" выражением extern "C"):

#include <stdio.h>

extern "C" {
#include "header.h"
}

int main() {
    union teststruct a;
    a.u64=5;
    printf("%x\n", a.u64);

    return 0;
}

Компиляция main.c с использованием строки

gcc -o test main.c

компилируется без проблем. Однако компиляция версии C++ с использованием компилятора g++ с командой

g++ -o test main.cpp

дает следующие ошибки компилятора:

In file included from main.cpp:12:0:
header.h:11:9: error: ‘u64 does not name a type
         u64 x:32;
         ^
header.h:12:9: error: ‘u64 does not name a type
         u64 y:32;
         ^

Проблема заключается в том, что поставщик использовал то же имя (u64) как для типа, так и для имени переменной, которое, похоже, представляет собой плохую идею, но gcc, по-видимому, принимает его. Я не хочу менять библиотеку (например, header.h), поскольку она очень большая, в коде это очень много, и я иногда получаю обновления для нее. Есть ли способ заставить g++ принять эту комбинацию или способ изменить main.cpp, чтобы он скомпилировался без изменения header.h?

Ответ 1

teststruct определяет область действия в C++. Вы можете сформировать квалифицированный id teststruct::u64. Таким образом, для этого используются правила языка для поиска имени, позволяющие членам классов и профсоюзов скрывать идентификаторы во внешней области. После u64 u64; , неквалифицированный u64 не может ссылаться на глобальный ::u64, только член. И член не тип.

В C union teststruct не определяется область действия. Поле может использоваться только в доступе к члену, поэтому конфликт никогда не возникает. Таким образом, поле не должно скрывать идентификатор типа области файла.

Нет ничего, насколько я могу судить, что вы можете сделать, чтобы легко обойти это. Эта библиотека (которая является вполне допустимой библиотекой C) не является допустимой библиотекой C++. Не иначе, как если бы он использовал new или try как имена переменных. Его нужно адаптировать.

Ответ 2

Кажется, у вас есть файл заголовка, который является незаконным в C++, поэтому вы не можете #include его в код, скомпилированный как C++. Если вы не можете повлиять на изменение в файле заголовка библиотеки (например, жалуясь поставщику библиотеки), самым простым вариантом является написать тонкую C++ -совместимую оболочку вокруг библиотеки:

Чтобы изолировать ваш код C++ от заголовка C, создайте Wrapper.h и Wrapper.c, где .h действителен для включения в C++, не включает header.h и предоставляет все типы и функции, которые вы необходимость взаимодействия с библиотекой. Затем в .c вы можете #include "header.h" и реализовать все вызовы (и все, что вам нужно сделать для безопасного преобразования между типами). Это, очевидно, должно быть скомпилировано как C, а не C++.

Ответ 3

Если ваша упомянутая несовместимость между C и C++ является единственной, вы должны иметь возможность конвертировать header.h в C++ совместимый файл заголовка программным header.hpp, назовите его чем-то вроде header.hpp. И тогда вы можете конвертировать более новые версии одинаково.

Ошибки компилятора сообщают вам все о том, что и где следует изменить:

header.h:11:9: error: ‘u64 does not name a type
  1. Открыть header.h;
  2. Ищите позицию 11: 9;
  3. Вставить :: там;
  4. Повторить для всех does not name a type ошибку does not name a type.

Некоторая обработка строк и все сделано.

Преобразователи PS: C на C++ тоже могут это сделать.