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?
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);
}
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++.
Related
I've been using C++ and compiling with clang++. I would like to include the <xcb/xkb.h> header for an X11 program I am writing.
Unfortunately this header uses explicit for some field names (such as line 727) and that is a keyword in C++.
Is there anyway to deal with this?
xcb/xkb.h:
// ...
#ifdef __cplusplus
extern "C" {
#endif
// ...
typedef struct xcb_xkb_set_explicit_t {
xcb_keycode_t keycode;
uint8_t explicit;
} xcb_xkb_set_explicit_t;
// ...
#ifdef __cplusplus
}
#endif
// ...
Use a macro to rename the fields:
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif
#define explicit explicit_
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#include <xcb/xkb.h>
#undef explicit
Using a keyword as a macro name is ill-formed in standard C++, but GCC, Clang (with pragma), and MSVC do accept it. (The standard says you "shall not" do it, cppreference clarifies that it means "ill-formed".)
How can I include a C header that uses a C++ keyword as an identifier in C++?
There is no standard-conforming solution to be able to include such header. In order to be able to include a header in C++, it must be written in valid C++. In case of a C header, it would thus have to be written in common subset of C and C++.
The ideal solution is to fix the header to be valid C++. A standard-conforming workaround is to write a C++ conforming wrapper in C.
(Not an answer to the exact question, but possibly useful for the general problem of interfacing C & C++)
How about using an intermediate set of C files (.c & .h) to wrap the incompatible header and provide a C++-compatible interface to the rest of your program? If that interface is high-level enough, then you would only need to include the incompatible header file in the wrapper .c file only, allowing the wrapper .h header file to be included in C++ code normally.
Depending on the details, you might end up doing some trivial copying of data, but the resulting C interface might be much more suited to your specific needs.
One solution is to add a generation step to your makefile that copies the header and renames the field, and include said autogenerated header instead.
(This is between difficult to impossible to do in the general case, but in this case given that the header isn't likely using explicit for anything else even just a simple (gnu) sed (s/\bexplicit\b/explicit_field/g or somesuch) would work. The trickier bit is figuring out the correct file to copy.)
Make sure that the location of the copied header is before the original header in your include path, in case something else in your includes indirectly includes the header.
Just changing a field name shouldn't have any effects on e.g. ABI, at least for a nominally-C-compatible header. (There are cases in C++ where renaming a field does affect things.)
I have code written in C only. The main function is main.c, and it include other c files like #include "Flash.h".
I would like to keep the project working but to be able to add a cpp file .
I was told that I have to change the main to be
main.cpp
which will produce 250 errors on compilation- regarding the included c files
What's the proper way to turn the main file to cpp and still include C files ?
main.cpp :
#include "Flash.h"
int main(void)
{
....
}
I have read How to use C source files in a C++ project? which did not provide me a direct solution to the problem (my compiler will use c++ anyway).
EDIT:
Before someone will kill me for asking (don't know why you are so aggressive), I get only 3 kinds of errors 250 times :
'->' cannot appear in a constant-expression
'&' cannot appear in a constant-expression
a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
EDIT 2 :
Here are some of the lines ( running using SDK for some RF chip ):
Most of the errors are from this section
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_GPIOTE_TASKS_OUT_0 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0.*/
NRF_GPIOTE_TASKS_OUT_1 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1.*/
NRF_GPIOTE_TASKS_OUT_2 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2.*/
NRF_GPIOTE_TASKS_OUT_3 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3.*/
#if (GPIOTE_CH_NUM > 4) || defined(__SDK_DOXYGEN__)
NRF_GPIOTE_TASKS_OUT_4 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4.*/
NRF_GPIOTE_TASKS_OUT_5 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5.*/
NRF_GPIOTE_TASKS_OUT_6 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6.*/
NRF_GPIOTE_TASKS_OUT_7 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7.*/
On these lines the same error repeat :
a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
The #include directive in C++ is a literal inclusion of source code. Imagine your C source code in Flash.h included by main.c doing something incompatible with C++ like
typedef int class;
Now, in your main.cpp you have
#include "Flash.h"
It's exactly as if you had this code typedef int class; directly in your C++ source file - so it's an error.
If you have C source code with C headers, you don't need to use C++ at all!
If you want to write new C++ code and make it call old code (or vice-versa), just use the linker. Have C++ code include C++ headers, and separately, C code include C headers, and the linker will combine all your code into an executable.
To make your C and C++ parts work together, you need an additional header file. For example call it c-cpp-interface.h. Then include it in all your C and C++ source files:
#include "c-cpp-interface.h" // in C files
extern "C" {
#include "c-cpp-interface.h" // in C++ files
}
This file should be written in a common C/C++ subset language. That is, mostly, C language but with increased type safety (e.g. prototypes for all functions must be written fully, without the implied ... arguments).
Ideally, your existing C header file could be used as such. However, C header files often accumulate cruft, and it might be more practical to create a new file than clean the existing one(s).
Looking at the actual error messages you have (with offsetof), you should try to have as little code as possible in the C - C++ interface. Don't put implementation details (like values of various constants) there. Only have there the declarations/prototypes for functions that are called by the other language (C calling C++ or vice versa).
The question you post points out you need to wrap the inclues
extern "C" {
#include "cheader.h"
}
In your case,
extern "C" {
#include "Flash.h"
}
int main(void)
{
}
and in each cpp that wants to use C code, use extern "C" round the include.
I am using GCC C++ 11 in CodeBlocks IDE. I have been trying to reuse classes that I wrote by putting them into a header file but it doesn't work. I have looked into many books but none has detailed information on making C++ code reusable.
There are a couple concepts that C++ uses that I think you're missing:
The difference between a declaration and a definition
#include statements
Linking against other libraries
In general, one reuses code in C++ by Declaring a function in a header file (.h), Defining it in a source file (.cpp). The header file ("foo.h") is then included in both the source file (foo.cpp) and any other file you want to use something declared in it using and preprocessor include directive #include "foo.h". Finally if the source file in which the functions declared in the header file are defined is not a part of the source for the library or executable that you're compiling, you will need to link against the library in which it was built.
Here's a simple example that assumes that you don't need to link against an external library and that all files are in the same directory:
foo.h:
The class Foo is declared along with a member function foobar and a private member variable barM. In this file we're telling the world that there is a class named Foo, it's constructor and destructor are public, it has a member function named fooBar that returns an integer and it also has a private member variable named barM.
class Foo
{
public:
Foo();
~Foo();
int fooBar();
private:
int barM;
};
foo.cpp
The individual member functions for our class Foo are defined, we implement the things we declared in the header file. Notice the include statement at the top
#include "foo.h"
Foo::Foo()
{
barM = 10;
}
Foo::~Foo()
{
}
int Foo::fooBar()
{
return barM;
}
main.cpp
We use our class in a different file, again the header file is included at the top.
#include <stdio.h>
#include "foo.h"
int main(int argc, char *argv[])
{
Foo flub;
std::cout << "flub's fooBar is: " << flub.fooBar() << std::endl();
return 0;
}
The expected output from this would be:
flub's fooBar is 10.
As a general note, I haven't compiled this code, but it should be enough to give you a basic example of the ideas of declarations, definitions, and include statements.
Seeing as you're coming from Java, I'm actually betting that you got all of that already, the hard part is actually using code from a different c++ library, which is akin to Java packages. Setting this up requires exporting the symbols you desired to use in a different library. The way to do this is compiler specific, but is generally accomplished by defining a Macro in a different header file and then using that macro in the declaration of the item you'd like to export. For gcc, see reference GNU Reference Manual.
To extend the above example you create another header file: fooLibExport.h
#if BUILDING_LIBFOO && HAVE_VISIBILITY
#define LIBFOO_DLL_EXPORTED __attribute__((__visibility__("default")))
#elif BUILDING_LIBFOO && defined _MSC_VER
#define LIBFOO_DLL_EXPORTED __declspec(dllexport)
#elif defined _MSC_VER
#define LIBFOO_DLL_EXPORTED __declspec(dllimport)
#else
#define LIBFOO_DLL_EXPORTED
#endif
foo.h would then be changed to:
#include "fooLibExport.h"
class LIBFOO_DLL_EXPORTED Foo
{
public:
Foo();
~Foo();
int fooBar();
private:
int barM;
};
Finally you'll need to link against the library that Foo was built into. Again this is compiler specific. At this point we're through the setting up of header files for exporting symbols from a C++ library so that functions defined in one library can be used in another. I'm going assume that you can follow the reference material for setting up the GCC compiler for the rest of the process. I've tried to bold the key words that should help refine your searches.
One final note about #include statements, the actual argument isn't just the filename, its the path, relative or absolute, to the file in question. So if the header file isn't in the same file as the file you're trying to include it in, you'll need to use the appropriate path to the file.
Code re-usability casts its net wide in C++ terminology. Please be specific what do you mean by it.C and C++ programming language features usually considered to be relevant to code reuse could be :-
functions, defined types, macros, composition, generics, overloaded functions and operators, and polymorphism.
EDITED IN RESPONSE TO COMMENT:-
Then you have to use header files for putting all declarations which you can use in any file just by including this.
I had a C dynamic library, due to some requirement change I have to do some refactoring.
I had following code in one c file.
__attribute__((noinline))
static void *find_document(...)
{
...
}
bool docuemnt_found(const char *name) {
...
find_document(...);
...
}
I separated the docuemnt_found() function in different cpp file. Now docuemnt_found() function cannot link to find_document() method?
I tried creating header for the c file and then include header using extern "C" but it did not work.
I want to keep find_document() inline. Is there anything missing here or something wrong?
The problem here is the declaration of the function as static - in C, this says that it should be available to other functions within the same compilation unit (.c file), but not to other functions outside the file. Removing static should solve the problem.
Incidentally, the second function is misspelled - it should be document_found, not docuemnt_found.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Use the keyword class as a variable name in C++
In a C header file of a library I'm using one of the variables is named 'new'. Unfortunately, I'm using this library in a C++ project and the occurence of 'new' as a variable names freaks out the compiler. I'm already using extern "C" { #include<...> }, but that doesn't seem to help in this respect.
Do I have to aks the library developer to change the name of that variable even though from his perspective, as a C developer, the code is absolutely fine, as 'new' is not a C keyword?
Before including the header file, use the preprocessor to rename new:
#define new mynew
#include <...>
#undef new
That will allow the compilation to proceed.
Do you actually need to access this variable? If not - then you're done. If you do, then you'll need to ensure the .c files for the library are compiled with
-Dnew=mynew
Is it required that the header contain the name of this variable? If you are using a global variable named "new", then of course that would be a reason it is required that you have a globally visible variable name. On the other hand, if this is something like a function argument named "new", simply delete the name from the declaration of the function. If the name is a member of a structure or union, changing it in the header file will not harm the .C code as long as the .C code sees a "private" definition with the name matching that source code.
Since the .C files should be compiled in C syntax and thus will be able to cope with the variable named "new," fixing the header files ought to be a valid work-around.
For the long-term, yes you should bring this to the attention of the library developer.
As a final, somewhat hacky, solution, you could change the header file from "new" to something, e.g., "was_new." And when compiling the C files of the library use compiler switches to enforce #define new was_new.
You could write your own wrapper functions in C. Everything that you use that will touch the library will be written in C with C++ friendly header files. So, instead of:
other_lib.h:
int foo( int new );
my_app.cxx:
extern "C" {
#include <other_lib.h>
}
which won't compile, you do:
my_wrap.h:
#ifdef __cplusplus
extern "C" {
#endif
int my_foo( int );
#ifdef __cplusplus
}
#endif
my_wrap.c:
#include <other_lib.h>
int my_foo( int x ) { return foo( x ); }
my_app.cxx:
#include "my_wrap.h"
...
Compile my_wrap.c with a C compiler, then compile my_app.cxx with the C++ compiler.
This allows you to build while making no changes to the existing library.
If you are modifying a perfectly fine header file of a 3rd party library, I'd recommend that you'd stop now. You are attempting to add C++ code to a C library if I understood you right, that will not do, C does not recognize the "new" keyword as it's a C++ keyword.
Instead I'd recommend that :
You create a separate C++ project with a source file (*.cpp), add an #include to that 3rd party header file, and link (google "linking libs" etc.) the library's binary file to your project.
I hope that helps a bit,
Cheers