【问题标题】:Use C library in a C++ code with non-compatible code在具有不兼容代码的 C++ 代码中使用 C 库
【发布时间】:2019-05-13 11:42:02
【问题描述】:

我想在 C++ 代码中使用 C 库,而不对其进行修改。

该库包含与 c++ 不兼容的代码片段,例如:

  • C++ 关键字newdelete
  • _Atomic对象
  • 错误的声明

我将 C 库编译成 .so。而且我还在另一个 C 代码上使用了它,它运行良好(实际上我想制作这段代码的 C++ 版本)。

我的 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")

我的标题以 :

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

我有很多错误。一点汇编:

/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__};           \

【问题讨论】:

  • 库的实际接口似乎使用了 C++ 中不存在的 C 特定功能。这使得无法完全使用 C++ 中的库。请记住,C 和 C++ 确实是两种不同的语言,尽管有一些共同的继承和语法。
  • 可能可以通过为库的接口编写自己的头文件来解决这些问题,但是如果您需要调用的函数使用纯 C 功能或结构,那么这是不可能的。如果是这种情况,您需要编写一个包装 C 库来充当 C++ 和实际库之间的接口。或者,当然,找到另一个满足您需求的库。
  • 感谢您的回答。所以我需要做一个包装?包装器是 C 或 C++ 代码?
  • 连接您的 C++ 程序和 C 库的包装库也必须在 C 中。它必须在 C 中,否则它会遇到您已经遇到的相同问题。
  • 好的,所以我将修改我之前使用 frr C 库的 C 代码并将 main 函数转换为我将在我的 cpp 程序中调用的函数,对吧?

标签: c++ c cross-language


【解决方案1】:

一个简单的(虽然可能不是唯一的)解决方案:

为您的 C 库编写一个精简的 C++ 绑定 shim。

由于您的库包含与 C++ 不兼容的 C 代码 - 不属于两种语言的公共子集 - 您必须编写 C++ 可以使用的绑定。这些将需要用 C 而不是 C++ 编写

我们将您编写的绑定 shim 文件称为 frr_cpp_bindings.hfrr_cpp_bindings.c

shim 的头文件frr_cpp_bindings.h 将公开与libfrr.h 基本相同的内容,但没有任何实际代码(如./r.inf = &_frrmod_info)——只有在C++ 和C 的公共子集中的函数和类型定义.

这个 shim (frr_cpp_bindings.c) 的实现将直接包含 libfrr.h,基本上只是将调用转发到 libfrr.h-暴露的 C 函数。

最后,在frr_cpp_bindings.h 文件中,你可以有这样的东西:

#ifdef __cplusplus
extern "C" {
#endif

// all of the actual C code

#ifdef __cplusplus
}
#endif

这意味着您不需要在 C++ 代码中使用extern "C"

最后,您的 C++ 源文件将具有:

#include <frr_cpp_bindings.h>

并且不会尝试直接包含不兼容的标头。

【讨论】:

  • “在 C 中,而不是在 C 中”?我假设您的意思是“在 C 中,而不是在 C++ 中”?
  • 如果 C++ 绑定“shim”头文件正确完成,它内部将包含 extern "C" 部分。
  • 好的,所以当我编译时,我应该同时编译包装器和我的 cpp 代码吗?
  • @PierreI:您单独编译包装器,并单独编译您的 CPP 代码;它们是两个不同的 TU。
  • @PierreI:如果可行,请接受答案并投票。
猜你喜欢
  • 2016-08-26
  • 1970-01-01
  • 2022-01-04
  • 2014-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多