c++ - 使用 C 而不是 C++ 编译头文件

标签 c++ c eclipse cmake

我有一个 C++ 项目,我已使用 Cmake 配置该项目以使用 Eclipse。我的问题是我添加了一个静态 C 库(即 svm-struct/svm-light),它似乎无法编译 - 我的猜测是它编译为 C++ 而不是 C。

我将库添加到我的项目中,如下所示:

SET(SVM_LIGHT_SRC_DIR "../../Libraries/svm_rank")
INCLUDE_DIRECTORIES(${SVM_LIGHT_SRC_DIR})

ADD_LIBRARY(
    svm_rank_lib STATIC
    ${SVM_LIGHT_SRC_DIR}/svm_light/svm_learn.c
    ${SVM_LIGHT_SRC_DIR}/svm_light/svm_common.c
    ${SVM_LIGHT_SRC_DIR}/svm_light/svm_hideo.c
    ${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_learn.c
    ${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_common.c
    ${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_classify.c
    ${SVM_LIGHT_SRC_DIR}/svm_struct_api.c
    ${SVM_LIGHT_SRC_DIR}/svm_struct_learn_custom.c
)

add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} svm_rank_lib)

Cmake 配置看起来不错。在配置的输出中,它指定它找到我的 C 和 C++ 编译器并且它们“工作”。我使用 extern 将 header 添加到我的项目文件之一,如下所示:

#ifdef __cplusplus
extern "C" {
# include "svm_struct/svm_struct_common.h"
}
#endif

当我去构建我的项目时,错误在这里:

../../Libraries/svm_rank/svm_struct/../svm_struct_api_types.h:75:11: error: expected member name or ';' after declaration specifiers
  double *class;    /* vector of scores that imply ranking */
  ~~~~~~  ^
1 error generated.

库头中有一个名为“class”的变量,其中发生了错误,我的猜测是它试图使用 C++ 而不是 C 来编译此库头。首先,这是错误的原因吗?如果是这样,我应该如何解决这个问题?

最佳答案

正如已经指出的,问题的根源在于C库头声明了一个名为class的变量,它是C++中的关键字。

一旦该 header 被 C++ 源文件拉入,这个问题就会出现。请记住, header 本身不是编译的,而只是由预处理器复制粘贴到#include包含它们的源文件中。源文件的类型决定了 header 中的代码是解释为 C 还是 C++。

将包含内容包装在 extern "C" 中的事实不会改变这一点。它只是switches off C++-style name mangling对于 header 中的声明,但代码仍然必须编译为有效的 C++。

此问题最干净的解决方案是一种称为“绝缘”或编译器防火墙的技术。

您必须确保与有问题的库接触的所有部分本身都是 C 源文件。代码的 C++ 部分仅通过该 C 部分的接口(interface)与库交互,但从不直接与库交互。特别是,您绝对不能从任何头文件中#include 库头。

例如: my_interface.c

#include "svm_struct/svm_struct_common.h"  /* safe to include from a .c file */

struct opaque_ {
     /* you can use types from svm_struct_common in here */
};

opaque* initialize()
{
     /* you can create an opaque_ on the heap and
        manipulate it here, as well as give a
        pointer back to the C++ part */
}

void do_stuff(opaque*)
{
    /* do whatever you like with the stuff in opaque */
}

my_interface.h

/* no #includes in the header! */

/* the opaque type is only forward declared!
   C++ code can obtain a pointer to it,
   but cannot look inside */
struct opaque_;
typedef struct opaque_ opaque;

opaque* initialize();
void do_stuff(opaque*);

my_application.cpp

// we only include our own header, which we made sure is valid C++
extern "C" {
    #include <my_interface.h>
}

void do_stuff()
{
    opaque* context = initialize();
    do_stuff(context);
}

关于c++ - 使用 C 而不是 C++ 编译头文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29637842/

相关文章:

c - 内核驱动程序: How get correct content of each variable in a struct?

android - Fabric for Android Studio/Eclipse - 无法与其他用户登录

c++ - 单独文件中的函数实现

c++ - 在 C++ 中使用非默认构造函数初始化对象的成员类

_Generic 可以是一个函数吗?或者 _Generic 可以与 __attribute__((cleanup)) 一起使用吗?

c - 提示如何早于 popen 调用的标准输出出现?

java - 更改打开帮助搜索首选项

java - Eclipse 控制台不显示输出

c++ - 配饰设计

c++ - glColor3f 仅颜色为红色