【问题标题】:Compiling header using C, instead of C++使用 C 而不是 C++ 编译头文件
【发布时间】:2015-06-20 16:23:22
【问题描述】:

我有一个使用 Cmake 配置以使用 Eclipse 的 C++ 项目。我的问题是我添加了一个似乎无法编译的静态 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 来编译这个库头。首先这是错误的原因吗?如果是这样,我应该如何解决这个问题?

【问题讨论】:

  • 类是保留字
  • @cssGEEK 准确地说:class 是保留关键字。
  • 如果您使用的是gcc,您可以使用-Wc++-compat 标志要求它指出您的C 代码中的此类潜在问题。
  • 是的,我知道class是c++中的保留关键字,但是头文件是C,我的理解“class”不是保留关键字。我知道我可以修补库,但我想找到解决方案而不必这样做。

标签: c++ c eclipse cmake


【解决方案1】:

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

只要 C++ 源文件引入该标头,就会遇到此问题。请记住,标头不是自己编译的,而只是由预处理器复制粘贴到#includes 的源文件中。源文件的类型决定了标头中的代码是被解释为 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);
}

【讨论】:

  • 我忘了感谢你的回答,最后帮了大忙:)
【解决方案2】:
double *class;    /* vector of scores that imply ranking */

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

编辑

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

【讨论】:

  • 再一次,这应该是 C 中的标头,据我了解,“类”不是保留关键字。因此我猜测它是编译为 C++ 而不是 C。
  • 然后显示你的make文件。如果 Eclipse 必须有一些选项可以从 g++ 更改为 gcc。我不使用eclipse,所以我帮不上忙。使用 C 中可能没有的保留字的变量名是不好的做法。只是为了让您的代码也与 C++ 兼容。
猜你喜欢
  • 2012-12-02
  • 2020-10-24
  • 2022-06-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2011-08-10
  • 2017-08-23
相关资源
最近更新 更多