Как обработать заголовочный файл C ++ с помощью внешнего вызова функции C и объекта класса - PullRequest
1 голос
/ 19 февраля 2020

Я пытаюсь скомпилировать приложение, включающее файлы C и C ++. С одним конкретным заголовком я сталкиваюсь с проблемами. Рассматриваемый файл (заголовочный файл C ++) будет выглядеть примерно так:

#ifndef TASK_H
#define TASK_H

#include "MyCCPObject.h"

int foo1(int);
int foo2(int);
int fooObject(MyCCPObject myCppObject); // Function involves a Class "MyCCPObject" type

#ifdef __cplusplus
extern "C" {
#endif
    int foo3(void); // Function called in a C file
#ifdef __cplusplus
}
#endif

#endif //TASK_H

У меня есть функция fooObject(), у которой в качестве параметра указан тип класса MyCCPObject. Кроме того, одна из функций foo3() будет вызываться из файла C. Когда компилятор C компилирует этот заголовок, я получаю следующую ошибку: "error: #20:identifier "class" is undefined". Чтобы избежать этого, я должен был:

  1. Поместить объявление fooObject() в ограждение компилятора:
#ifdef __cplusplus
int fooObject(MyCCPObject myCppObject);
#endif
Поместите защиту компилятора также в объявление класса в заголовочном файле MyCCPObject.h:
#ifdef __cplusplus
class MyCCPObject
{
public:
    MyCCPObject(uint32_t val);
private:
    uint32_t value;

};
#endif

Примечание: MyCCPObject не будет вызываться ни в одном файле C. Итак, что было бы лучше, когда у меня есть заголовочный файл C ++, который включает в себя:

  1. Функция будет включать в себя объект класса
  2. A extern вызов C файл

Ответы [ 2 ]

2 голосов
/ 19 февраля 2020

Используйте отдельные заголовки для кода C и C ++.

Переместите объявление foo3 (включая элементы защиты __cplusplus) в отдельный заголовок. Давайте назовем это Foo3.h Теперь у вас есть следующие файлы:

  • Task.h - содержит объявления для foo1 и foo2, fooObject и включает MyCCPObject.h
  • Foo3.h - содержит объявления для foo3
  • Task.cpp - включает Task.h и Foo3.h и предоставляет определения для foo1, foo2 и foo3
  • App.c - включает Foo3.h и использует foo3

Из вашей системы сборки (make, cmake et c.) При сборке библиотеки C ++ добавьте файлы Task.h, Foo3.h, Task.cpp (и другие файлы, связанные с MyCCPObject)

При создании приложения C добавьте только Foo3.h и App.c. Таким образом, другие заголовки (которые содержат код C ++) не будут скомпилированы и, следовательно, не будут выдавать никаких ошибок.

1 голос
/ 19 февраля 2020

Создатели C ++ написали FAQ , который также дает некоторые рекомендации по , как смешивать C и C ++ . Они также рассматривают возможность использования объектов C ++ из C code .

Option 1 : если вы просто хотите, чтобы компилятор C имел возможность для анализа вашего заголовочного файла task.h, вы можете скрыть части C ++, которые я использовал #ifdef __cplusplus:

#ifndef TASK_H
#define TASK_H

#ifdef __cplusplus
#include "MyCCPObject.h"

int foo1(int);
int foo2(int);
int fooObject(MyCCPObject myCppObject); // Function involves a Class "MyCCPObject" type

extern "C" {
#endif
    int foo3(void); // Function called in a C file
#ifdef __cplusplus
}
#endif

#endif //TASK_H

Option 2 : если вы хотите сделать функцию fooObject доступно из C, затем вы можете изменить MyCppObject.h, чтобы предоставить полную информацию о классе для C ++ и только минимальный typedef для C. typedef гарантирует, что C понимает только имя класса MyCCPObject без записи class или struct перед ним.

#ifdef __cplusplus
class MyCCPObject
{
public:
    MyCCPObject(uint32_t val);
private:
    uint32_t value;

};
#else
typedef struct MyCCPObject MyCCPObject;
#endif

и task.h в

#ifndef TASK_H
#define TASK_H

#include "MyCCPObject.h"

int foo1(int);
int foo2(int);

#ifdef __cplusplus
extern "C" {
#endif
    int fooObject(MyCCPObject *myCppObject); // Function involves a Class "MyCCPObject" type
    int foo3(void); // Function called in a C file
#ifdef __cplusplus
}
#endif

#endif //TASK_H

Обратите внимание, что мне нужно было изменить подпись fooObject, чтобы получить указатель на объект, так как код C не видит полный класс и не знает размер объекта.

...