Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use C library in a C++ code with non-compatible code

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__};           \
like image 626
Pierre I Avatar asked May 13 '19 11:05

Pierre I


1 Answers

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.

like image 105
einpoklum Avatar answered Nov 15 '22 04:11

einpoklum