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

时间:2015-04-14 21:37:07

标签: 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将标题添加到我的一个项目文件中:

#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来编译这个库头。首先,这是错误的原因吗?如果是这样,我该如何解决这个问题呢?

2 个答案:

答案 0 :(得分:2)

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

只要该标头被C ++源文件拉入,就会遇到此问题。请记住,标头不是由它们自己编译的,而是仅由预处理器复制粘贴到#include它们的源文件中。它是源文件的类型,用于确定标头中的代码是否被解释为C或C ++。

您在extern "C"中包含包含这一事实并未改变这一点。对于头文件中的声明它只是switches off C++-style name mangling,但代码仍然必须编译为有效的C ++。

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

您必须确保与有问题的库接触的所有部件都是C源文件本身。代码的C ++部分只通过该C部分的接口与库交互,但不会直接与库交互。特别是,您绝不能从任何头文件中#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);
}

答案 1 :(得分:0)

double *class;    /* vector of scores that imply ranking */
如果有帮助,

类以蓝色突出显示。是保留字,意味着您不能将其用作变量或宏名称。尝试更改它,它应该删除错误。

修改

我误解了你是用C编译的,但似乎是用C ++编译的。但我仍然坚持我的答案,最好更改变量类以保持代码与C ++兼容,因为类是C ++中的保留字。