如何通过对 C 函数的外部调用和 class object 处理 C++ header 文件

How to handle a C++ header file with a extern call to C function and a class object

我正在尝试编译一个同时涉及 C 和 C++ 文件的应用程序。对于一个特定的 header 我遇到了问题。有问题的文件(C++ header 文件)看起来像这样:

#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 class 类型作为参数。此外,其中一个函数 foo3() 将从 C 文件中调用。 当 C 编译器编译此 header 时,出现以下错误:"error: #20:identifier "class" is undefined"。为了避免这种情况,我不得不:

  1. fooObject() 声明放在编译器保护中:
#ifdef __cplusplus
int fooObject(MyCCPObject myCppObject);
#endif
  1. 将编译器保护也放在 header 文件的 class 声明中 MyCCPObject.h:
#ifdef __cplusplus
class MyCCPObject
{
public:
    MyCCPObject(uint32_t val);
private:
    uint32_t value;

};
#endif

注意:MyCCPObject 不会在任何 C 文件中调用。 那么,当我有一个 C++ header 文件时,什么是更好的方法,其中涉及:

  1. 函数将涉及 class object
  2. A extern 调用 C 文件

C++ 的创造者写了一个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

选项 1:如果您只是希望 C 编译器能够解析您的 task.h 头文件,那么您可以使用 [= 隐藏 C++ 部分13=]:

#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

选项 2:如果要使 fooObject 函数可从 C 访问,则可以更改 MyCppObject.h 以提供完整的 class 信息到 C++,只有最小的 typedef 用于 C。 typedef 确保 C 只理解 class 名称 MyCCPObject 而无需编写 classstruct之前。

#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 代码看不到完整的 class 并且不知道对象的大小.

为您的 C 和 C++ 代码使用单独的 header。

foo3 声明(包括 __cplusplus 守卫)移到单独的 header 中。我们称它为 Foo3.h 您现在拥有以下文件:

  • Task.h - 包含 foo1foo2fooObject 的声明并包括 MyCCPObject.h
  • Foo3.h - 包含 foo3
  • 的声明
  • Task.cpp - 包括 Task.hFoo3.h 并提供 foo1foo2foo3
  • 的定义
  • App.c - 包括 Foo3.h 并使用 foo3

从您的构建系统(make、cmake 等)构建 C++ 库时,添加文件 Task.hFoo3.hTask.cpp(以及与MyCCPObject)

构建 C 应用程序时,仅添加 Foo3.hApp.c。这样,其他 headers(包含 C++ 代码)将不会被编译,因此不会给出任何错误。