1

I am trying to compile an application involving both C and C++ files. With one particular header I face issues. The file in question (a C++ header file), would look something like this:

#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

I have a function fooObject() which has a MyCCPObject class type as a parameter. Also, one of the functions, foo3() would be called from a C file. When the C compiler, compiles this header, I get the following error: "error: #20:identifier "class" is undefined". To avoid this, I had to:

  1. Place the fooObject() declaration within compiler guards:
#ifdef __cplusplus
int fooObject(MyCCPObject myCppObject);
#endif
  1. Place compiler guards also in the class declaration in the header file MyCCPObject.h:
#ifdef __cplusplus
class MyCCPObject
{
public:
    MyCCPObject(uint32_t val);
private:
    uint32_t value;

};
#endif

Note: The MyCCPObject would not be called in any C file. So, what would be a better approach, when I have a C++ header file, which involves:

  1. Function would involves a class object
  2. A extern call to a C file
Werner Henze
  • 16,404
  • 12
  • 44
  • 69
mmcblk1
  • 158
  • 1
  • 3
  • 10
  • Can you list all the file names with their contents? – Phalgun Feb 19 '20 at 19:15
  • Well, when the whole application is being compiled, the C compiler throws errors about ´"identifier "class" is undefined´, since the header file is included the C file due to the ´extern´ call. To avoid this, I had used compiler guards. Now am not sure if this is the right approach. – mmcblk1 Feb 19 '20 at 19:17
  • @Phalgun In my case, the `task.h` is the include file in question. The `task.cpp` file would the compiled file, but a couple of methods, like the `fooObject(MyCCPObject)`, and it would also use objects of type `MyCCPObject`. Next comes the C file, some `App.c`, wherein the function `foo3()` would be called. – mmcblk1 Feb 19 '20 at 19:23

2 Answers2

2

Use separate headers for your C and C++ code.

Move the foo3 declaration (including the __cplusplus guards) inside a separate header. Let's call it Foo3.h You now have the following files:

  • Task.h - contains the declarations for foo1 and foo2, fooObject and includes MyCCPObject.h
  • Foo3.h - contains the declarations for foo3
  • Task.cpp - includes Task.h and Foo3.h and provides definitions for foo1, foo2 and foo3
  • App.c - includes Foo3.h and uses foo3

From your build system (make, cmake etc.), when building the C++ library, add the files Task.h, Foo3.h, Task.cpp (and the other files related to MyCCPObject)

When building the C application, add only Foo3.h and App.c. That way, the other headers (which contain C++ code) will not be compiled and hence not give out any errors.

LWolf
  • 188
  • 1
  • 2
  • 7
1

The makers of C++ wrote a FAQ which is also giving some guidance on how to mix C and C++. They are also looking at the possibility to use C++ objects from C code.

Option 1: If you just want the C compiler to be able to parse your task.h header file, then you could hide the C++ parts my using #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: If you want to make the fooObject function accessible from C, then you can change MyCppObject.h to provide the full class information to C++ and only a minimal typedef for C. The typedef makes sure that C understands just the class name MyCCPObject without writing class or struct before it.

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

};
#else
typedef struct MyCCPObject MyCCPObject;
#endif

and task.h to

#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

Please note that I needed to change the signature of fooObject to take a pointer to the object as the C code does not see the complete class and does not know the size of the object.

Werner Henze
  • 16,404
  • 12
  • 44
  • 69