【问题标题】:How to handle a C++ header file with a extern call to C function and a class object如何使用对 C 函数和类对象的外部调用来处理 C++ 头文件
【发布时间】:2020-02-19 19:06:50
【问题描述】:

我正在尝试编译一个涉及 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
  1. 将编译器保护也放在头文件MyCCPObject.h的类声明中:
#ifdef __cplusplus
class MyCCPObject
{
public:
    MyCCPObject(uint32_t val);
private:
    uint32_t value;

};
#endif

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

  1. 函数将涉及类对象
  2. extern 调用 C 文件

【问题讨论】:

  • 有什么问题,你想达到什么目标?
  • 你能列出所有文件名及其内容吗?
  • 好吧,当整个应用程序被编译时,C 编译器会抛出关于“标识符”类“未定义”的错误,因为头文件包含在 C 文件中,因为“extern”调用. 为了避免这种情况,我使用了编译器保护。现在不确定这是否是正确的方法。
  • @Phalgun 在我的例子中,task.h 是有问题的包含文件。 task.cpp 文件是编译后的文件,但有几个方法,如fooObject(MyCCPObject),它也将使用MyCCPObject 类型的对象。接下来是 C 文件,一些 App.c,其中将调用函数 foo3()

标签: c++ c cross-language


【解决方案1】:

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

foo3 声明(包括__cplusplus 保护)移动到单独的标头中。我们就叫它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。这样,其他头文件(包含 C++ 代码)将不会被编译,因此不会出现任何错误。

【讨论】:

    【解决方案2】:

    C++ 的开发者写了一个FAQ,它也对how to mix C and C++ 提供了一些指导。他们也在寻找use C++ objects from C code的可能性。

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

    #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 以向 C++ 提供完整的类信息,并且只需一个最小的 typedef 用于C. typedef 确保 C 只理解类名 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 代码看不到完整的类并且不知道对象的大小。

    【讨论】:

      猜你喜欢
      • 2017-11-11
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2011-11-21
      • 2020-12-25
      相关资源
      最近更新 更多