Are there any pitfalls when calling functions from a C library in a C++ program?
I'm using a library which has both a C interface and a C++ interface in my C++ program. The C++ one is a bit immature and I must stick with the C one. I was wondering, in more general terms, is there anything speci开发者_StackOverflowfic to keep in mind when mixing C-style binary object files with a C++ project?
For C functions to be called from C++, they have to be declared as extern "C"
. Usually something like this is used in headers:
#if defined(__cplusplus)
extern "C" {
#endif
void f();
void g();
#if defined(__cplusplus)
}
#endif
C functions have to be declared as extern "C", if your C header files don't do this automatically, you can do it like this for the whole header:
extern "C"
{
#include "c-library.h"
}
Otherwise, as long as you use a C++ linker for everything all will be fine :).
One thing that is very useful when dealing with C libraries from C++ is RAII. Say if your C library has an initialization and release functions, that could be easily wrapped into resource-managing class:
#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
};
This of course makes the child class non-copyable, but that can be worked around via containment and/or smart pointers.
Calling C functions from C++ programs is pretty common. There is only one thing to keep in mind - use a C++ linker :) Also keep in mind that C functions cannot use exceptions, so you have to check their return values.
Edit: others have pointed out that C function declarations should be wrapped in extern "C" {...}
. Usually this is already done in library header files.
精彩评论