Search code examples
c++cportabilitysuppress-warnings

How to link old C code with reserved keywords in it with C++?


I have a 10+ years old C library which -- I believe -- used to work just fine in the good old days, but when I tried to use it with a C++ source (containing the main function) the other day I ran into some difficulties.

Edit: to clarify, the C library compiles just fine with gcc, and it generates an object file old_c_library.o. This library was supposed to be used in a way so that the C header file old_c_library.h is #included in your main.c C source file. Then your main C source file should be compiled and linked together with old_c_library.o via gcc. Here I want to use a C++ source file main.cpp instead, and compile/link it with g++.

The following three problems occurred, during the compilation of the C++ source file:

  1. one of the header files of the C library contains the C++ reserved word new (it is the name of an integer), which resulted in fatal error; and
  2. one of the header files of the C library contains a calloc call (an explicit typecast is missing), which resulted in fatal error; and
  3. various files of the C library contain code where comparison of signed and unsigned integers happen, which resulted in warnings.

Edit: I tried to use the #extern "C" { #include "obsolete_c_library.h" } "trick", as suggested in the comments, but that did not solve any of my problems.

I can sort out problem 1 by renaming all instances of the reserved words and replacing them by -- basically -- anything else. I can sort out problem 2 by typecasting the calloc call. I might try to sort out the warnings by ideas suggested here: How to disable GCC warnings for a few lines of code.

But I still wonder, is there a way to overcome these difficulties in an elegant, high-level way, without actually touching the original library?


Relevant: Where is C not a subset of C++? and Do I cast the result of malloc? and How do I use extern to share variables between source files?.


Solution

  • Generally speaking, it is not safe to #include C header files into C++ sources if those headers were not built in anticipation of such usage. Under some circumstances it can be made to work, but you need to be prepared to either modify the headers or write your own declarations for the functions and global variables you want to access.

    At minimum, if the C headers declare any functions and you are not recompiling those functions in C++ then you must ensure that the declarations are assigned C linkage in your C++ code. It's not uncommon for C headers to account for that automatically via conditional compilation directives, but if they do not then you can do it on the other side by wrapping the inclusion(s) in a C linkage block:

    extern "C" {
    #include "myclib.h"
    }
    

    If the C headers declare globals whose names conflict with C++ keywords, and which you do not need to reference, then you may be able to use the preprocessor to redefine them:

    #define new extern_new
    #include "myclib.h"
    #undef  new
    

    That's not guaranteed to work, but it's worth a try. Do not forget to #undef such macros after including the C headers, as shown.

    There may be other fun tricks you can play with macros to adapt specific headers to C++, but at some point it makes more sense to just copy / rewrite the needed declarations (and only those), either in your main C++ source or in your own C++ header. Note that doing so does not remove the need to declare C linkage -- that requirement comes from the library having been compiled by a C compiler rather than a C++ compiler.