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
- Открыть
header.h
; - Ищите позицию 11: 9;
- Вставить
::
там; - Повторить для всех
does not name a type
ошибку does not name a type
.
Некоторая обработка строк и все сделано.
Преобразователи PS: C на C++ тоже могут это сделать.