2

I have a C++ project that I have configured using Cmake to use Eclipse. My problem is that I have added a static C library (namely, svm-struct/svm-light) which doesn't seem to compile- and my guess is that it's compiling as C++ instead of C.

I added the library to my project as follows:

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 configures fine it seems. Within the output of the configuration it specifies that it finds my C and C++ compilers and that they "work". I add the header to one of my project files using extern as follows:

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

When I go to build my project the error is here:

../../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.

There is a variable within the library header called "class" where the error occurs, and my guess is that it's trying to compile this library header using C++ instead of C. First of all is this the reason for the error? If so, how should I go about fixing this?

ABC
  • 665
  • 1
  • 6
  • 15
  • 1
    Class is a reserved word – cssGEEK Apr 14 '15 at 21:38
  • 2
    @cssGEEK To be precise: `class` is a reserved keyword. – πάντα ῥεῖ Apr 14 '15 at 21:39
  • 1
    If you are using `gcc`, you can ask it to point out such potential problems in your C code by using the `-Wc++-compat` flag. – Edward Apr 14 '15 at 21:46
  • 1
    yes, I understand class is a reserved keyword in c++, but the header file is C, where to my understanding "class" is not a reserved keyword. I understand I can patch the library but I wanted to find a solution without having to do that. – ABC Apr 14 '15 at 23:50

2 Answers2

3

As has already been pointed out, the source of the problem is that the C library header declares a variable named class, which is a keyword in C++.

This problem will hit you as soon as that header is pulled in by a C++ source file. Remember that headers are not compiled by themselves, but are merely copy-pasted by the preprocessor into the source file that #includes them. It is the type of the source file that determines whether the code in the header is interpreted as C or C++.

The fact that you wrapped the include in extern "C" does not change this. It simply switches off C++-style name mangling for the declarations in the header, but the code still has to compile as valid C++.

The cleanest solution to this problem is a technique known as insulation or compiler firewall.

You have to make sure that all parts that come into contact with the problematic library are C-source files themselves. The C++ part of your code only interacts with the library through the interface of that C part, but never with the library directly. In particular, you must never #include library headers from any of your header files.

For instance: 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);
}
Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
0
double *class;    /* vector of scores that imply ranking */

class as highlighted in blue if it helps. Is a reserved word meaning you can't use it as a variable or macro name. Try changing it and it should remove the error.

Edit

I misunderstood you are compiling in C but it seems to compile in C++. But I still stand by my answer its best to change the variable class to keep the code compatible with C++ as class is a reserved word in C++.

Community
  • 1
  • 1
Daniel Lopez
  • 1,728
  • 3
  • 24
  • 40
  • again, this is header is supposedly in C, where to my understanding "class" is not a reserved keyword. Hence my guess that it's compiling as C++ instead of C. – ABC Apr 14 '15 at 23:51
  • Then show your make file. If eclipse there has to be some option to change from g++ to gcc. I do not use eclipse so I can't be of help. Its bad practice to use a variable name of a reserved word that may not in C. Just to keep your code compatiable with C++ as well. – Daniel Lopez Apr 16 '15 at 15:45