【发布时间】:2010-04-13 21:38:45
【问题描述】:
我在我的 C++ 程序中使用了一个同时具有 C 接口和 C++ 接口的库。 C++ 有点不成熟,我必须坚持使用 C。我想知道,更笼统地说,在将 C 风格的二进制对象文件与 C++ 项目混合时,有什么需要特别注意的吗?
【问题讨论】:
我在我的 C++ 程序中使用了一个同时具有 C 接口和 C++ 接口的库。 C++ 有点不成熟,我必须坚持使用 C。我想知道,更笼统地说,在将 C 风格的二进制对象文件与 C++ 项目混合时,有什么需要特别注意的吗?
【问题讨论】:
对于要从 C++ 调用的 C 函数,它们必须声明为 extern "C"。通常在标题中使用这样的东西:
#if defined(__cplusplus)
extern "C" {
#endif
void f();
void g();
#if defined(__cplusplus)
}
#endif
【讨论】:
C 函数必须声明为 extern "C",如果您的 C 头文件不自动执行此操作,您可以对整个头执行此操作:
extern "C"
{
#include "c-library.h"
}
否则,只要您使用 C++ 链接器,一切都会好起来的 :)。
【讨论】:
extern "C"。
在从 C++ 处理 C 库时非常有用的一件事是RAII。假设你的 C 库有初始化和释放函数,可以很容易地封装到资源管理类中:
#include <boost/utility.hpp>
/// Base class for top-level library objects
class lib_base: boost::noncopyable
{
protected:
lib_base()
{
if ( my_c_lib_init() == -1 )
throw std::runtime_error( "no C lib" );
}
~lib_base() { my_c_lib_fini(); }
};
/// Widget from C library
class widget: lib_base
{
public:
widget( const std::string& name ) :
lib_base(), pcw_()
{
if (( pcw_ = my_c_lib_alloc_widget( name.c_str())) == NULL )
throw std::runtime_error( "no more widgets" );
}
~widget() { my_c_lib_release_widget( pcw_ ); }
private:
c_widget* pcw_; //< low-level widget
};
这当然使子类不可复制,但这可以通过包含和/或智能指针来解决。
【讨论】:
从 C++ 程序调用 C 函数是很常见的。只需要记住一件事 - 使用 C++ 链接器 :) 还要记住 C 函数不能使用异常,因此您必须检查它们的返回值。
编辑:其他人指出 C 函数声明应该包含在 extern "C" {...} 中。通常这已经在库头文件中完成了。
【讨论】: