(A case of over relying on an IDE)
I have some legacy C code that I compile as C++ for the purpose of Unit testing. The C source is C++ aware in that it conditionally defines based on environment.
E.g. (PRIVATE resolves to static):
#if!defined __cplusplus
#define PRIVATE1 PRIVATE
#endif
...
PRIVATE1 const int some_var;
The problem is I just can't seem to find out what PRIVATE1 resolves to or is in C++, the compiler complains of redefinition if I add a declaration but doesn't indicate where?
I have searched my MinGW/gcc include path, the C++ ISO specification and the C++ books available to me has been to no avail.
Edit:
Sure I checked the command line and makefiles before posting.
There's nothing like this in ISO C++ spec. Most likely, PRIVATE1 (as well as PRIVATE) are defined elsewhere in the project. Note that this doesn't need to be a #define in an .h file - it can also be defined via compiler switches in the makefile. I'd suggest doing a full grep on the project directory.
If PRIVATE1 resolves to PRIVATE, and PRIVATE resolves to static, then PRIVATE1 resolves to static.
It's unlikely (but not impossible) that they are defined by MinGW itself. Macros defined by the C++ or C implementation should begin with an underscore.
Eclipse C++ managed project's are a little, well stupid!
If a project is declared C++ it still bases it's build on file extension, hence .h file preprocessed as C and not C++ header which pulls in a #define PRIVATE1 from another header file similarly wrapped by:
#ifdef __cpluplus.
The project is then linked by g++.
Your best bet is to look at the preprocessor output. You didn't post what compiler you are using, but if you check the docs, most have an option to "Preprocess to file" which will create a file with all the macros substituted. This might be able to help you figure out what is happening. In Visual Studio you use the /E option (under C/C++->Preprocessor->Generate Preprocessed File) which will turn foo.c into foo.i. This file will generally be HUGE compared to the original source file, so scroll down to the bottom to see your code.
Most likely in C++ it's defined to, well, "private:".
Can you declare a function with PRIVATE1? If so, just write a function like so:
PRIVATE1 void Foo() {
// __FUNCSIG__ in Visual Studio, not sure about GCC
std::cout << __FUNCSIG__ << std::endl;
}
Related
I have an third party source file and corresponding header (containing the declarations and include directives for GSL etc) which are written in C. I am trying to build an R package around these source files, basically making a wrappers for the functions using Rcpp. Problem is that these files contain restrict qualifier which is not part of the C++ standard, so R CMD INSTALL cannot compile the package. It does use C compiler for .c file, but want's to compile .h file with C++ compiler and it fails. it fails when it finds restrict in header file (which is included in .cpp file).
I am not that familiar with C and compiler things and Rcpp etc, so I am not sure what would be a best approach here?
Easiest thing would probably be to remove the restrict keyword. This is what I have currently done (I am suprised that R CMD INSTALL works when I remove restrict from header file but leave them to .c file). But I rather not alter the .c and .h files as they are also used in non-R environment by others (executable and in Python) and it would be nice to have identical files for all projects.
I also tried to define empty keyword restrict so that it would just "remove" restrict from function definitions if the compilation was done in C++ compiler, but I couldn't get that work. I read about similar approach somewhere but apparently it doesn't work that way.
Would it work if I could somehow tell the compiler (via Makevars or something?) that the particular .h file should be compiled with C compiler? Or is there going to be problems with C++ function calling those functions?
Or will the whole keyword even matter in terms of performance if those functions are called from R via C++ wrapper?
One thing would be to just ditch the Rcpp and use .C instead of .Call from R, but as the performance is a key here, that doesn't feel a good option, as I understand that .Call is faster (and more reliable).
Note that eventually this package could find it's way to CRAN, so the solution should be fairly portable. There seems to be some C++ compiler specific keywords for restrict but I guess those are not an option due to the portability.
It sounds like you are making a .cpp file which does #include <x.h> where x.h is a C header which uses restrict. If that's true, I think you can modify your .cpp file to do this:
#define restrict // nothing
extern "C"
{
#include <x.h>
}
Then compilation of your C++ code will not see the restrict keyword, and also I have wrapped the header in extern "C" because if the header itself doesn't do that internally, you need to, in order that your C++ compiler will not apply C++ "name mangling" to the functions declared inside.
I have a C++ file that compiles fine in one project, but not in another. The file is the exact same C++ file in both projects.
Both projects are MFC dialog-based projects. They have slightly different stdafx.h files... but if I'm prepared to break the rest of the project, I can make them identical... and still get this compiler error. Equally, they have considerably different include paths, but if I break even more of the project and make the include paths identical, I still get the error. It goes without saying that I have made all my preprocessor directives identical... and I still get the error.
So, as far as I can tell, I'm down to compiler switches. I've made them identical (within reason - I haven't bothered to change the /Fp, /Fd or /Fo output files), but still it refuses to compile. Are there any "hidden" settings or anything else that might be affecting compilation?
[Note: the following is included mostly for historical reasons - it led to an unintentional over-emphasis when this question was originally posed, and so led to predictable comments and answers which didn't help resolve the intended "when is identical not identical?" question]
The error itself is error 2894 (templates cannot have 'C' linkage). I understand this error, but not how/why it is occurring. It occurs within a bunch of C header files pertaining to a C library. They are all neatly wrapped in extern "C" {...} declarations, with #ifdef __cplusplus correctly applied. But extern C {...} is not something I'm very familiar with, so... is there anything special about extern "C" {...} that might be a factor?
If a single C++ file is compiled under the same conditions, it leads to the same result. It doesn't matter if it is in a project with zero other files, or a hundred other files - the compiler compiles each file individually.
Therefore, if a single C++ file compiles with different results, then that is either because:
It is not really the same single C++ file, or
It is not really the same compilation conditions.
You can see exactly what the Microsoft Visual C++ compiler thinks your "single" C++ file truly is by specifying /showIncludes as an "advanced" compiler option. You might be surprised to see how different your "identical" C++ file is (and this was the case here).
Equally, you can see the explicit C++ compiler conditions listed under the Command Line summary that appears at the bottom of the list of C/C++ options in the project properties in Visual Studio.
wspapi.h includes some C++ template code outside of its internal extern "C" section. If you were to externally wrap the header in an extern "C" declaration, you would break it.
For example, you cannot do this:
extern "C"
{
#include <wspapi.h>
}
Similarly, if a preceding header or code has failed to terminate an extern "C" block so that all the content of the header is given C linkage, the same situation arises.
Put simply, wpsapi.h has been included within a C linkage block, it has nothing to do with "hidden options".
If I use gcc as a driver, call all my source files .c and .h, can I be sure that I wont have any C++ source in my sources? Are there any gcc parameters to make sure that he throws errors in case any c++ is encountered in the source?
I am especially paranoid about include files, because I am not 100% sure whether I include C headers or C++ headers.
Some examples I ran into in the past:
trying to use the type bool
using wrong includes cstdio vs. stdio.h
trouble with the struct keyword
I just want to make 100% sure that my source is only C and has no C++ in it.
GCC will figure out itself whether it's a C or a C++ source code. How? It scans the file extension the file you passed has.
These are the extensions accepted.
In case you want to force a specific language, use the -x flag (documented in the link above). Furthermore, you may check whether the macro __cplusplus is defined.
I am relatively new to Mixed C/C++ applications using the gcc and g++ tools.
To get the hand of it I have downloaded the iperf source code and built it with success using Eclipse.
There is one oddity: If I look into the file "Thread.c" using Eclipse it thinks there is a syntax error and underlines almost the whole file as if the code is flawed, which it is absolutely not.
This is the piece of code that triggers it:
#ifdef __cplusplus
extern "C"
{
#endif
I know what extern "C" is used for in C++ but Eclipse has problems with it when present in .c files. It happily accepts it in .cpp and .h files though.
I have checked out how the Make utility builds the iperf application and I see it always uses gcc to compile c files and g++ to compile cpp files which makes me wonder if extern "C" is actually required. It most definitely does not hurt because the gcc compiler happily deals with it but if it is not strictly required I could omit it and get better readability in Eclipse.
I have also looked at a possible solution for Eclipse's behaviour but have not really found one, if anybody can point out how to solve it that would be equally good.
If you are using Eclipse, what you seeing in editor has to do with Eclipse internal indexer/parser. Your mixed C/C++ project may compile and build with no issues, but when you open a source file which has
#ifdef __cplusplus
extern "C" {
#endif
you may see a syntax error marked on the extern "C" line. This means that "__cplusplus" symbol is defined for your C compiler in your project settings.
In order to get rid of that syntax error in the Eclipse editor, go to project Properties -> C/C++ General -> Paths and Symbols -> # Symbols tab, and select "GNU C" (or whatever C compiler you use) under "Languages" column. Scroll through Symbol/Value list on the right, find the "__cplusplus" symbol and delete it. Make sure you do that only for C compiler.
Click OK to close the project Properties window and the syntax error warning will be gone in Eclipse editor.
that piece of code is normally found in headers, and should be always be written to header files that belong to c-files. (with the corresponding closing bracket at the end of the header)
reason is, that c uses a different scheme how the functions are internally called (--> name mangeling). while the compiler can distinguish a c++ code file from c code file by its extension it can not distinguish between a c-header and a c++ header that is included from a cpp file. so it does not know if it has to mangle the name of the declared functions or not (by default it does).
then the linker tries to match the used symbols (reference to function from cpp) with the created one (defined by the c-file) it does not find the symbol if the compiler was not told not to mangle the declaration.
extern "C" is only legal in C++ and ensures that the specified function(s) have C linkage. This means that the function parameters are not mangled into the binary function name.
To ensure that the header file compiles in C we include the #ifdef __cplusplus __cplusplus is defined by a C++ compiler and not a C compiler. This use used to protect C code from the C++ only extern "C" directive.
IDE's so not use compilers for code intelligence and therefore may get things wrong.
probably just a silly workaround for your issue.
what i found is that, while using c functions in cpp file, theoretically extern is required.
But i found that in eclipse oxygen version, we do not have to specify extern c, we can directly use c functions and printf statements too in cpp file and it just works fine.
Havent tried in older versions of eclipse.
My solution may not be very helpful, but you could give it a try. It worked for me.
In our company sometimes we write .cpp and .h files, which are used in projects for old WM (we use Embedded Visual C++ 3.0 or something for this) and in more modern code (VS 2010).
This Embedded Visual C++ does not support STL.
So if one of developers, who works in VS2010, changes a file, which is shared, and adds some function, which uses std::vector, for instance, on his side everything will be OK, but the build (which is quite long) will fail.
So to see this mistake sooner, I would like to add something like
#if defined(%%STL%%)
#error("!!!!")
#endif
in all files, which are compiled with old toolset. In this case the developer could see compile time error even in VS2010.
But I could not find what I can put instead %%STL%% there.
Any ideas? Or maybe someone knows a better way how I can do this?
Based on a comment to the question, you could go through each of the header files that aren't supported and see what symbols they define for their include guard. Then check for those symbols being defined.
E.G. The Microsoft C++ header <algorithm> defines _ALGORITHM_ so you can check for that:
#ifdef _ALGORITHM_
#error("<algorithm> included")
#endif
A bunch of these could be collected up and put into a single header file that you could include in each shared source file, at the end.
There is quite a nice solution (at least I do not see pitfalls)
%%STL%% should be _STD_BEGIN
this macro is used for "namespace std {" in VS stl implementation