C vs C ++ несовместимость компиляции - не называет тип - PullRequest
0 голосов
/ 27 июня 2018

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

Я упростил свой код в следующих файлах примеров. header.h представляет заголовок из вспомогательной библиотеки, 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"):

#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?

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

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

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

0 голосов
/ 28 июня 2018

Если упомянутая вами несовместимость между 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 ++ тоже могут это делать.

0 голосов
/ 27 июня 2018

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

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

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

...