5

I want to use a C library in a C++ code, without modifying it.

The library contains fragment of code non-compatible with c++ like :

  • C++ keyword new and delete
  • _Atomic object
  • bad declaration

I compiled the C library into a .so. And I also used it on an another C code and it worked perfectly (in fact I want to made a C++ version of this code).

My CMakeLists :

# Specify the minimum CMAKE version required
cmake_minimum_required(VERSION 2.8)

# Project name
project(myproject)

# Header files
set(HEADERS myCpp.h)

# Source files
set(SOURCES myCpp.cpp)
add_executable(myproject myCpp.cpp myCpp.h)

# Link libraries
LINK_DIRECTORIES(/usr/lib/libfrr.so)
target_link_libraries(${PROJECT_NAME}  frr)


set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
set(CMAKE_CXX_FLAGS "-fpermissive")

My header starts with :

extern "C"{
        #include "lib/libfrr.h"
}

I've got a tons of errors. A little compilation :

/lib/module.h:88:3: error: expected primary-expression before '.' token
   .r.info = &_frrmod_info,        

/lib/thread.h:123:2: error: '_Atomic' does not name a type
  _Atomic unsigned int total_active;

lib/memory.h:163:13: error: 'struct memtype' has no member named     'n_alloc'
  return mt->n_alloc;

/lib/libfrr.h:88:25: sorry, unimplemented: non-trivial designated     initializers not supported
          __VA_ARGS__};           \
einpoklum
  • 86,754
  • 39
  • 223
  • 453
Pierre I
  • 53
  • 4
  • 1
    It seems the actual interface of the library is using C-specific functionality that doesn't exist in C++. That makes it impossible to fully use the library from C++. Remember, C and C++ are really two different languages, despite some common heritage and syntax. – Some programmer dude May 13 '19 at 11:45
  • You *might* be able to work around the problems by writing your own header file for the interface to the library, but if functions you need to call use C-only functionality or structures, then it's not possible. If that is the case, you need to write a wrapper C library to act as an interface between C++ and the actual library. Or, of course, find another library that fulfill your needs. – Some programmer dude May 13 '19 at 11:46
  • Thanks for your answers. So I need to make a wrapper ? The wrapper is a C or a c++ code ? – Pierre I May 13 '19 at 11:50
  • 1
    The wrapper library that bridges your C++ program and the C library also have to be in C. It must be in C because otherwise it will have the very same problems you already have. – Some programmer dude May 13 '19 at 11:52
  • Ok, so I will modify my previous C code that used the frr C library and turn the main function into a function that I will call in my cpp program right ? – Pierre I May 13 '19 at 11:55
  • Where did you get your library? My search for libfrr returns a library that appears to be C++ friendly by design. – n. 'pronouns' m. May 13 '19 at 16:36
  • here : https://github.com/FRRouting/frr – Pierre I May 14 '19 at 15:44
  • Headers of this library are all wrapped in `extern "C"` so you don't need to bother. Furthermore the content of the library does not correspond to the error messages. Some line numbers are of and some of the code isn't present at all. Make sure you have an up to date copy of the library. – n. 'pronouns' m. May 14 '19 at 17:45

1 Answers1

8

A straightforward (though perhaps not the only) solution:

Write a thin C++ bindings shim for your C library.

Since your library contains C code which is not C++-compatible - not in the common subset of both languages - you have to write bindings which C++ can use. These will need to be written in C, not in C++.

Let's call the bindings shim files you write frr_cpp_bindings.h and frr_cpp_bindings.c.

The shim's header file, frr_cpp_bindings.h, will expose essentially the same thing as libfrr.h, but without any actual code ( like ./r.inf = &_frrmod_info ) - only function and type definitions which are in the common subset of C++ and C.

The implementation of this shim (frr_cpp_bindings.c) will include libfrr.h directly and basically just forward calls to to libfrr.h-exposed C functions.

Finally, in the frr_cpp_bindings.h file, you can have something like this:

#ifdef __cplusplus
extern "C" {
#endif

// all of the actual C code

#ifdef __cplusplus
}
#endif

and this means you won't need to extern "C" in the C++ code.

Finally, so your C++ source files will have:

#include <frr_cpp_bindings.h>

and will not try to include the incompatible header directly.

einpoklum
  • 86,754
  • 39
  • 223
  • 453