Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?.

like image 880
Matsmath Avatar asked Apr 26 '16 14:04

Matsmath


People also ask

Can reserved words in C language be chosen as variable names?

A variable name must not be any reserved word or keyword, e.g. int, goto, etc.

Is register a reserved keyword in C?

In the C programming language, register is a reserved word (or keyword), type modifier, storage class, and hint.

How many reserved keywords are there in C?

Keywords are predefined, reserved words in C language and each of which is associated with specific features. These words help us to use the functionality of C language. They have special meaning to the compilers. There are total 32 keywords in C.


2 Answers

  1. You can write a duplicate of the c header with the only difference being lack of declaration of extern int new. Then use the newly created c++ friendly header instead of the old, incompatible one.

    If you need to refer that variable from c++, then you need to do something more complex. You will need to write a new wrapper library in c, that exposes read and write functions a pointer to c++ that can be used to access the unfortunately named variable.

    If some inline functions refer to the variable, then you can leave those out from the duplicate header and if you need to call them from c++, re-implement them in a c++ friendly manner. Just don't give the re-implementation same name within extern "C", because that would give you a conflict with the original inline function possibly used by some existing c code.

  2. Do the same header duplication as described in 1. leaving out the problematic inline function and re-implementing if needed.

  3. Warnings can be ignored or disabled as you already know. No need to modify the original headers. You could rewrite any {const,type}-unsafe inline functions with versions that don't generate warnings, but you have to consider whether your time is worth it.

The disadvantage of this approach is that you now have two vesions of some/all of the headers. New ones used by c++, and the old ones that may be used by some old code.


If you can give up the requirement of not touching the original library and don't need to work with an existing compiled binary, then an elegant solution would be to simply rename the problematic variables (1.). Make non-c++-compatible inline functions (2.) non-inline and move them into c source files. Fix unsafe code (3.) that generates warnings or if the warning is c++ specific, simply make the function non-inline.

like image 31
eerorika Avatar answered Nov 15 '22 22:11

eerorika


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.

like image 117
John Bollinger Avatar answered Nov 15 '22 21:11

John Bollinger