在C代码中使用C ++库


102

我有一个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原理#ifndef __cplusplus #error在这里使用东西有助于发现任何疯狂。
  2. 小心C ++标识符作为C代码中的名称
  3. C和C ++编译器之间的枚举大小不同。如果您使用的是GNU工具链,则可能不是问题,但仍然要小心。
  4. 对于结构,请遵循以下格式,以免C混淆。

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

所有这些都是由一位C ++向导的朋友提供的。


5
有点晚了,但是我写了一个关于C ++ C包装的小方法:teddy.ch/c
Teddy

Answers:


69

是的,这肯定是可能的。您将需要用C ++编写一个接口层,该接口层声明具有extern "C"以下功能:

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

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

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


应该extern "C"只放在声明中(而不是定义中)?因为您提到了“声明函数的层”,但是示例代码也是一个定义。换句话说,我们应该将其放置在头文件还是源文件中?(或同时放置在这两个文件中?)
kyriakosSt

@KyrSt:如果您有一个带有函数声明的头文件,那么您至少必须放置extern "C"在那里。您的编译器会告诉您是否还必须将其放在定义中。
Greg Hewgill


12

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


2
关于长跳电话的要点。尽管我不直接使用它们,但我使用的测试框架确实实现了它们。要记住的事情。谢谢
Misha M

3

您可以混合使用C / C ++代码。如果您的main()函数使用C ++编写,则只需确保声明了c函数

extern "C"

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.