Can we use POSIX C libraries in C ++?
2 answers
Basically, you should be able to use any C API from C ++; the language includes functions to facilitate it, and most C library authors know that people want to do this and will take the appropriate steps. For system programming interfaces specified in POSIX, C ++ compatibility is an explicit design goal.
However, you may still run into problems. In my experience, the most common problems are:
- API headers The API often dumps hundreds of characters into the global namespace. Some of these symbols can conflict with symbols in the C ++ library, which can get you in trouble if you
using namespace std
(but you didn't, did you?) - Macros are often used in API headers, including macro names that may conflict with symbols in the C ++ library;
std::
will not keep you there. - Compiling your program in strict match mode (for example
-std=c++11 -D_XOPEN_SOURCE=700
) can reveal errors in system headers. This is more likely to happen with C ++ than C. - A small subset of POSIX APIs have abnormal control flow behavior that can interact poorly with C ++ exceptions and destructors, depending on how careful your C library developer has been to avoid the problem.
setjmp
andlongjmp
obviously concern here (someone made the C library implementing the tops of exception handling DWARF style?) but alsofork
,setcontext
and friendspthread_cancel
,pthread_cleanup_push
and perhaps a few others I can not remember from the head. (I remember a giant, ultimately flimsy argument between Ulrich Drepper and the CCC C ++ guys back in 2004 or so of exactly how onepthread_cancel
should behave in the presence of destructors.)
If you go outside of POSIX you may also have problems with:
- Headers that didn't bother to wrap all the declarations in a
extern "C"
block when compiled in C ++, which means all function names get malformed when they shouldn't, and the linking fails. - Headers that didn't even bother sticking to the intersection of C and C ++. In the worst case, this can lead to crashes that do not appear until the program is started. The most common examples of this are:
- Blithely using some C ++ keyword as the declared name (for example
int template;
) - Assuming that
void *
is an assignment that is compatible with other types of pointers (e.g. no need to emit a resultmalloc
) - Assuming it
struct foo;
doesn't define a typedef-namefoo
- Blithely using some C ++ keyword as the declared name (for example
Note that headers referenced by POSIX often contain system extensions that have not been as carefully thought out as the POSIX interfaces themselves.
+6
source to share