【问题标题】:Using C++ library in C code在 C 代码中使用 C++ 库
【发布时间】:2022-01-04 21:43:45
【问题描述】:

我有一个 C++ 库,它提供了各种用于管理数据的类。我有这个库的源代码。

我想扩展 C++ API 以支持 C 函数调用,以便该库可以同时与 C 代码和 C++ 代码一起使用。

我使用的是 GNU 工具链(gcc、glibc 等),因此语言和架构支持不是问题。

是否有任何理由说明这是技术上不可能的?

有什么我需要注意的陷阱

是否有与此相关的资源、示例代码和/或文档?


我发现的其他一些事情:

  1. 使用以下内容来包装 C 代码需要使用的 C++ 标头。

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. 将“真正的”C++ 接口保存在 C 不包含的单独头文件中。请在此处思考PIMPL principle。在这里使用 #ifndef __cplusplus #error 的东西有助于发现任何疯狂。
  2. 小心 C++ 标识符作为 C 代码中的名称
  3. C 和 C++ 编译器之间的枚举大小不同。如果您使用 GNU 工具链,这可能不是问题,但还是要小心。
  4. 对于结构,请遵循以下格式,以免 C 混淆。

    typedef struct X { ... } X
    
  5. 然后使用指针来传递 C++ 对象,它们只需在 C 中声明为 struct X,其中 X 是 C++ 对象。

所有这一切都是由一位 C++ 天才朋友提供的。

【问题讨论】:

标签: c++ c gcc glibc


【解决方案1】:

是的,这当然是可能的。你需要用 C++ 编写一个接口层,用extern "C" 声明函数:

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

然后,您将从 C 模块调用 foo(),这会将调用传递给用 C++ 实现的 realFoo() 函数。

如果您需要公开一个包含数据成员和方法的完整 C++ 类,那么您可能需要比这个简单的函数示例做更多的工作。

【讨论】:

  • 是否应该只将extern "C" 放在声明中(而不是在定义中)?因为您提到了“声明函数的层”,但您的示例代码也是一个定义。换句话说,我们应该把它放在头文件还是源文件中?(或两者兼而有之?)
  • @KyrSt:如果你有一个带有函数声明的头文件,那么你至少必须把extern "C"放在那里。您的编译器会告诉您是否还必须将其放在定义中。
【解决方案2】:

您可以混合使用 C/C++ 代码。如果你的 main() 函数在 C++ 中,那么你只需要确保你的 c 函数被声明了

extern "C"

如果你的 main 是 C,那么除了静态变量之外你可能没问题。任何带有静态变量的构造函数都应该在 main() 开始之前被调用。如果 C 是您的主要内容,则不会发生这种情况。我你有很多静态变量,最好的办法是用单例替换静态变量。

【讨论】:

    【解决方案3】:

    主要问题:不能在 C 中捕获异常。如果 C++ 代码中可能出现异常,请非常小心地编写 C 代码或 C++ 包装器。相反,C 代码(在各种脚本语言中都可以找到)中的异常类机制(即 longjump)不需要为堆栈上的 C++ 对象调用析构函数。

    【讨论】:

    • 关于 longjump 调用的要点。虽然我不直接使用它们,但我使用的测试框架确实实现了它们。要记住的事情。谢谢
    【解决方案4】:

    C++ FAQ Lite:"How to mix C and C++ code".

    这些问题的答案中描述了一些问题:

    • [32.8] 如何将 C++ 类的对象传入/传出 C 函数?
    • [32.9] 我的 C 函数能否直接访问 C++ 类的对象中的数据?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 2015-07-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-09
      • 2013-10-09
      相关资源
      最近更新 更多