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


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

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

заголовок.ч (обратите внимание на строку 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

главная.c:

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

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

    return 0;
}

главная.СРР (аналогично главной.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, по-видимому, принимает его. Я не хочу менять библиотеку (т. е. заголовок.з) так как он очень большой,это происходит много в коде, и я иногда получаю обновления для него. Есть ли способ заставить g++ принять эту комбинацию или способ изменить main.cpp, чтобы сделать его компилировать без изменение заголовка.ч?

3   51   2018-06-27 14:03:39

3 ответа:

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

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

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

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

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

если ваша упомянутая несовместимость между C и C++ является единственной, вы должны иметь возможность конвертировать header.h чтобы c++ совместимый файл заголовка программно, назовите его что-то вроде 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 ошибка.

обработка строк и готово.

PS: конвертеры C в C++ тоже могут это сделать.