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
Related
I have a 10+ years old C library which -- I believe -- used to work just fine in the good old days, but when I tried to use it with a C++ source (containing the main function) the other day I ran into some difficulties.
Edit: to clarify, the C library compiles just fine with gcc, and it generates an object file old_c_library.o. This library was supposed to be used in a way so that the C header file old_c_library.h is #included in your main.c C source file. Then your main C source file should be compiled and linked together with old_c_library.o via gcc. Here I want to use a C++ source file main.cpp instead, and compile/link it with g++.
The following three problems occurred, during the compilation of the C++ source file:
one of the header files of the C library contains the C++ reserved word new (it is the name of an integer), which resulted in fatal error; and
one of the header files of the C library contains a calloc call (an explicit typecast is missing), which resulted in fatal error; and
various files of the C library contain code where comparison of signed and unsigned integers happen, which resulted in warnings.
Edit: I tried to use the #extern "C" { #include "obsolete_c_library.h" } "trick", as suggested in the comments, but that did not solve any of my problems.
I can sort out problem 1 by renaming all instances of the reserved words and replacing them by -- basically -- anything else. I can sort out problem 2 by typecasting the calloc call. I might try to sort out the warnings by ideas suggested here: How to disable GCC warnings for a few lines of code.
But I still wonder, is there a way to overcome these difficulties in an elegant, high-level way, without actually touching the original library?
Relevant:
Where is C not a subset of C++? and Do I cast the result of malloc? and How do I use extern to share variables between source files?.
Generally speaking, it is not safe to #include C header files into C++ sources if those headers were not built in anticipation of such usage. Under some circumstances it can be made to work, but you need to be prepared to either modify the headers or write your own declarations for the functions and global variables you want to access.
At minimum, if the C headers declare any functions and you are not recompiling those functions in C++ then you must ensure that the declarations are assigned C linkage in your C++ code. It's not uncommon for C headers to account for that automatically via conditional compilation directives, but if they do not then you can do it on the other side by wrapping the inclusion(s) in a C linkage block:
extern "C" {
#include "myclib.h"
}
If the C headers declare globals whose names conflict with C++ keywords, and which you do not need to reference, then you may be able to use the preprocessor to redefine them:
#define new extern_new
#include "myclib.h"
#undef new
That's not guaranteed to work, but it's worth a try. Do not forget to #undef such macros after including the C headers, as shown.
There may be other fun tricks you can play with macros to adapt specific headers to C++, but at some point it makes more sense to just copy / rewrite the needed declarations (and only those), either in your main C++ source or in your own C++ header. Note that doing so does not remove the need to declare C linkage -- that requirement comes from the library having been compiled by a C compiler rather than a C++ compiler.
You can write a duplicate of the c header with the only difference being lack of declaration of extern int new. Then use the newly created c++ friendly header instead of the old, incompatible one.
If you need to refer that variable from c++, then you need to do something more complex. You will need to write a new wrapper library in c, that exposes read and write functions a pointer to c++ that can be used to access the unfortunately named variable.
If some inline functions refer to the variable, then you can leave those out from the duplicate header and if you need to call them from c++, re-implement them in a c++ friendly manner. Just don't give the re-implementation same name within extern "C", because that would give you a conflict with the original inline function possibly used by some existing c code.
Do the same header duplication as described in 1. leaving out the problematic inline function and re-implementing if needed.
Warnings can be ignored or disabled as you already know. No need to modify the original headers. You could rewrite any {const,type}-unsafe inline functions with versions that don't generate warnings, but you have to consider whether your time is worth it.
The disadvantage of this approach is that you now have two vesions of some/all of the headers. New ones used by c++, and the old ones that may be used by some old code.
If you can give up the requirement of not touching the original library and don't need to work with an existing compiled binary, then an elegant solution would be to simply rename the problematic variables (1.). Make non-c++-compatible inline functions (2.) non-inline and move them into c source files. Fix unsafe code (3.) that generates warnings or if the warning is c++ specific, simply make the function non-inline.
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++.
I have a C library that I need to use in a C++ code, so I need to wrap the whole lib with an extern "C" block. The problem is that the library seems to include a C++ compiled code, so wrapping the whole lib would also wrap that C++ header.
Inside lib.h I only include all the internal headers I want to expose, something like this:
#ifndef LIB_H
#define LIB_H
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
#endif
So the client will only need to include lib.h to use the lib.
In my first attempt I've done this:
#ifndef LIB_H
#define LIB_H
extern "C" {
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
}
#endif
But then I get a symbol lookup error when I execute any function inside already_compiled_c++.h.
How can I avoid from applying extern "C" in the already_compiled_c++.h header file?
Edit:
Solved. This was not a problem using extern "C", it was a problem linking the compiled c++ library with gyp correctly: Using shared library in Gyp in node-sqlite3
Note that extern C isn't legal C, so it must only be included hen compiling as C++.
The already_compiled_c++.h header probably contains a guard against multiple includes, so just include it first:
#ifndef LIB_H
#define LIB_H
# This include added so that it won't get marked extern "C" when included by lob_foo.h.
#include <already_compiled_c++.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"
#ifdef __cplusplus
}
#endif
#endif
Note: You need to check if already_compiled_c++.h is conditionally included and add the corresponding conditionals.
You cannot call C++ from a file compiled in plain C.
If lib_foo.h is plain C, it cannot directly use the functions in already_compiled_c++.h. You will most likely need to create a C wrapper for it.
This answer may help you further: Elegantly call C++ from C
If your diagram is accurate, then lib_foo.h should not be including already_compiled_c++.h. Edit it to stop including that.
If the functions declared in already_compiled_c++.h had their implementation compiled to use the C++ ABI, there is no way that your C program could link against them. (short of extremely ugly hacking).
To avoid snarls like this in the future, explicitly put #ifdef __cplusplus extern "C" { guards in every header file which will have a C implementation, but might be used in a C++ program, and vice versa.
A workaround for your current situation would be to make a .cpp file that has thunks for the functions you need. Publish your thunks under extern "C", and implement them by calling the functions in already_compiled_c++.h.
Rethink your design. You can't include C++ headers from C, only the reverse. A few suggestions:
1) Although the original idea behind 'extern "C"' was to wrap includes of C headers from C++ files, if you have headers that should be C-accessible but are implemented in C++, the common approach is to wrap the declarations in it and not the includes. (With the requisite #ifdef __cplusplus so the C code, which always treats headers as being C, doesn't choke on the unneeded C++-ism 'extern "C"')
2) Don't expose C++ as the public API of a library. C++ in general does not provide a binary stable ABI. If you add a method and it's not at the end, or if you add an instance variable to a class, or if you change something in a templated class, all clients would have to be recompiled (with static libraries that usually happens anyway, but this is a big problem for dylibs/DLLs/frameworks). So in general the best idea is to keep C++ as an implementation detail and only expose C features from your library.
3) If you need to expose C++ from your library, use the Pimpl (private implementation) pattern and no templates, and put it in a separate header that isn't included by the master C header, so C clients can just not include it. Such a separate header is also useful for #2 because your library's modules' implementation files (which are in C++) can include it and thus use the classes in it.
4) To C++, a pointer to a struct Foo and a pointer to a class Foo are the same thing. So if you need to return a C++ class from a C-only API implemented behind the scenes in C++, what you can do is just always use struct Foo* in the headers (which C understands correctly), and provide C wrapper functions for the class's methods like:
extern "C" int FooGetCount( struct Foo* thisFoo )
{
return thisFoo->GetCount();
}
That way they can keep around pointers to C++ objects and access their properties, but don't need to actually use C++. Of course you also need to provide similar wrappers for creating/deleting the object, as C doesn't have the new/delete operators.
I have been believed that C header files must be included in the top level of C++ program.
Anyway, I accidentally discovered that C++ is allowing inclusion of C headers in a sub namespace.
namespace AAA {
extern "C" {
#include "sqlite3.h" // C API.
}
}
And then, all the C types and functions will be placed in the namespace. More interestingly, all the linked C functions are also just working! I also discovered that this may cause some preprocessor issue, but except that, it seems to be working pretty fine.
Is this a standard behavior? (I am using Clang 3.x) If it is, what is the name of this feature and where can I find this feature mentioned in the standard?
You may even do strange things like
//test.c
int
#include "main.h"
{
return 1;
}
//main.h
main(void)
The preprocessor macros are expanded before any syntax check is done. The above example will expand to
int
main(void)
{
return 1;
}
which is legal code. While you really should avoid such examples, there are cases, where including into another element is quite useful. In your question it depends on how the names are mangled during compilation. If all the definitions in your header file are declared with extern "C", the names will be searched unmangled in the object file, this is, however, not the case if the object file containing the implementation does not use the same namespace as it's definition in the consuming code and does not declare it extern "C".
Is this a standard behavior?
Yes - the behaviour is supported by the Standard, as the C++ compiler doesn't really have a notion of code being "C" versus "C++" except when extern "C" is used to inhibit namespace mangling.
The consequence of not inhibiting mangling is that you may end up with "unresolved symbol" errors at link time if you try to link with a C library defining the out-of-line symbols (extern variables, functions) mentioned in the header.
If it is [a Standard feature], what is the name of this feature and where can I find this feature mentioned in the standard?
This is just a consequence of the way #include works, which is defined in 16.2 Source file inclusion [cpp.include], crucially:
[an #include] causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters.
So, whatever happens with the "C" header is exactly as if the surrounding namespace/extern statements and braces existed at the top and bottom of the header file instead... by the time the next phase on compilation begins it's irrelevant exactly where the source code came from (except for purposes of displaying error messages that properly relate to the source file).
According to my requirement.
Suppose I have below files
abc.h //used for C file
int new; // All C++ keywords, new use as a variable
char class; // All C++ keywords, class use as a variable
Actual_task();
abc.c //C file
main()
{
...//Body of file where they have used new and class variable
new++; //for an example
class = 'C';
actual_task();//One function is getting called here
}
I have a .cpp file which needs the file abc.h needs to be included to use actual_task():
CPPfile.cpp
extern "C"{
#include "abc.h"
}
Then it throws errors like class and new can not used just like a variable.
Then how to use the C header files in cpp files?
You can't use C header files that use C++ keywords for other purposes than what they are meant for in C++.
The proper solution is to change the header file so it does not use the C++ keywords any more.
If the C++ keywords are used for global variables (that are not used by the C++ code) or function parameter names, you might get away with a construct like this:
#define new new_
#define class class_
extern "C" {
#include "abc.h"
}
#undef class
#undef new
Change the headers so that the variables / functions don't have names which are reserved words in C++.
If anyone says you can't then tell them you're being ask to merge source code from two separate programming languages which are, in this sense, incompatible. It's a known issue with a known solution.