C and C++ see which compiler used for which code - c++

Im currently working on a big project that uses C and c++ code in one project using the extern "c" keyword in my declartions.
However I am unsure whether the compiler is actually doing anything with this as my output is the same when using the C keyword.
Is there a way to print something to the console to show what compiler was used for a specific peice of code in my project or a way to see if something is actually being compiled in C or c++.
For example I tried using std::cout << something in the c code and it almost worked, the error didnt say anything like std not found or cout not found IIRC which I found to be a bit strange.
Ive tried googling this and didnt find any results.
Thanks for any help!
Edit.
Im using G++ as my compiler and would like the code to work on other compilers. my c code should work on both c and c++ but I need it to be C as im using union type pruning. Im at work right now so I cant recall the error message exactly. I also get the same ouput changing file extention to .c.
Is there a way to see if the code is being compiled as C or c++ thanks!

to answer your specific question about knowing if its a c or c++ compiler processing your code you can look for
__cplusplus
standard define
It's common to see:
#ifdef __cplusplus
extern "C"{
.....

It depends on the extention of your files for g++. If your file is .cpp g++ is used. If your file is .c then gcc is used.
Concerning extern "C" -- this is a cpp construct to inform the compiler that C abi should be used and none c++ name mangling applied. You can read on the mangling. As this construct has meaning for c++, i would expect it to be in a .cpp file.

Related

g++ - Finding appopriate Windows libraries to link so as to compile FANN library

For various reasons I have been trying to compile the FANN library myself. I'm on Windows 10 with MinGW. To keep things simple I was going for something like this to start with:
g++ mushroom.c -o shroom.exe -lm -I src\ -I src\include\ src\doublefann.c
(mushroom.c includes <stdio.h> and "fann.h".)
Using the -I src\ -I src\include\ src\doublefann.c allowed me to get rid of various undefined reference errors resulting from header files not being found, but it now keeps throwing the following undefined reference:
doublefann.c:(.text+0x4ee9): undefined reference to GetTickCount()
FYI, this appears in fann.h (line 54):
/* COMPAT_TIME REPLACEMENT */
#ifndef _WIN32
#include <sys/time.h>
#else /* _WIN32 */
#if !defined(_MSC_EXTENSIONS) && !defined(_INC_WINDOWS)
extern unsigned long __stdcall GetTickCount(void);
In short, this seems to be an error with linking windows libraries, and I don't really know how to proceed so as to find the relevant ones to link.
Here is the full fann.h and the full doublefann.c
DISCLAIMERS AND NOTES
EDIT: Since going to bed last night, I refined my approach so you don't have to edit the actual FANN source files. (For the record, my original approach worked and you can look at the edit history to see what that was if you really care).
Firstly, for anyone else stumbling across this question, I should note that it's not really necessary to use FANN this way. The website provides cmake files as well as Visual Studio Solutions that both work fine.
WHATS WRONG
Looking back at the question, the problem is obvious and I hate myself for not seeing it before the first of way too many hours. You'll notice that all of the files in that command have the *.c extension. Forgive me for treating you like a novice, but I can't assume you know anything or I risk giving a bad answer. *.c is the canonical file extension for C source files. The gnu toolchain is a fairly flexible piece of software, and you can compile C code with g++ without errors most of the time. But you shouldn't, because you'll get this error. Since your source file, mushroom.c, is a C source file, it'll work for you to just compile the code as C (in this case with gcc, not g++). If, however, you're using things in your program like iostream or string or classes or any other C++ code, you're right to compile it as C++ (by convention you would change the extension then to *.cpp for clarification, but I'm not sure the GNU toolchain cares). In that case, whenever you want to include C code in your C++ program, be sure to wrap it in an extern "C"{}, so that the compiler knows the calling conventions and labels are C standard, which isn't always the same as C++ standard. This means that not only does calling C code from C++ without extern "C" risk passing arguments to functions in the wrong way (good way to cause a segfault), but the way variables and functions are renamed when compiled to assembly is different between the two languages, which is why you get Undefined Reference in the linking stage, but not the compiling stage. In this case, not only is doublefann.c a C source file (which by itself links fine), but so is the library that contains the function declaration of GetTickCount(). Specifically, you're linking to %SYSTEMROOT%\System32\kernel32.dll (normally, but I believe MinGW uses PATH_TO_MinGW\lib\lib32k.a), which defines how programs can interact with the Windows Operating System at the machine-code level. The __stdcall utility is defined here to call things like GetTickCount() from the OS, which are assembly functions, within C code. Because this is in a *.dll, the compiler cannot change __stdcall to suit C++ coventions. This is due to the fact that "dll" stands for "Dynamically Linked Library". Essentially this means that these files were already compiled into machine code when Windows (or MinGW) was installed. So editing it is nonsensical, because you'd need to have intimate working knowledge of the opcodes for every x86_64 processor ever made. Thus, calling in C will do everything in a way that __stdcall expects, but calling in C++ requires the extern "C", or it'll mangle the names of your function declaration and possibly cause runtime errors.
tl;dr
FANN is written in C, C=/=C++, so don't expect a C++ compiler to always compile C code perfectly.
Solution
There are two ways to go about solving this problem.
1
If you're using C++ features/libraries, change the name of your source code to mushroom.cpp (if you want) and change the line (wherever it occurs in your program)
#include "doublefann.c"
to be wrapped like so:
extern "C"{
#include "doublefann.c"
}
If you read through fann.h, you might have noticed the lines:
#ifdef __cplusplus //line 65
extern "C"
{
#ifndef __cplusplus
} /* to fool automatic indention engines */
#endif
#endif /* __cplusplus */
Don't worry, these don't appear to conflict. Frankly, I'm not sure what these lines are meant to accomplish, but I'm sure they know what they're doing.
2
If mushroom.c really is just pure C, just compile using:
gcc -o shroom.exe mushroom.c -lm -I src\ -I src\ -I src\include\ src\doublefann.c -Wall
and that should work. I added -Wall because I love being able to make my code absolutely perfect, feel free to leave that out it just prints every warning you could have.

gcc Make sure that no c++ isms are compiled?

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.

is extern "C" required in C files ? (to solve odd Eclipse behaviour)

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.

Warnings when including C header file with C++ compiler

I have some header file that was written for use in a C99 program. This header includes all the function definitions, and is not paired with a source file. I am including it in a C++ file.
My C++ compiler flags include -pedantic -std=c++11, which gives me various warnings in the header file such as "ISO C++ forbids compound literals", and "ISO C++ forbids variable length arrays". Obviously the C++ compiler is treating the C99 code as C++. Two questions:
Is this a potential problem when trying to write code that will run correctly on various platforms using different compilers?
What is a good way to resolve the warnings, and produce standard conforming code? I was thinking of making a precompiled header file using gcc, but don't know enough about the process to be assured that I am not going to have unintended consequences from included a C precompiled header in a C++ source.
Thanks
Is this a potential problem when trying to write code that will run correctly on various platforms using different compilers?
Yes. GCC may just give a warning, other compilers (e.g. Visual Studio, or GCC with other options) could very well give an error.
What is a good way to resolve the warnings, and produce standard conforming code?
The correct way to resolve the problems is to write the header in the common subset of C and C++. Functions and object-definitions that use C99 features (such as variable-length arrays and compound literals) should be moved to a separate C source file (that gets compiled with a C compiler!).
To include a pure C header file(*) in a C++ project, you should wrap the include statement in an extern "C" block:
// C++
extern "C" {
// C-code goes here
#include "foo.h"
}
This is because C++ performs name mangling on all function names to make overloading work. C doesn't use name mangling, so C++ parses C function signatures with name mangling.
Please note that extern "C" doesn't put the compiler into "C-mode" (there is no such mode but you might falsely think of this instruction as such), it doesn't mangle the function names (+ changes the calling convention and forbids overloading; thanks for doomster for pointing these things out).
However, it shouldn't be a problem if you are including a header only (with inline implementations), since this name mangling will only be a problem when you link the C source file or library against your C++ project, since the function names are different in this case.
This being said, you should use the common subset of C and C++ for the header file, extract and compile the implementations of these functions separately with a C compiler, not C++. Then, you (hopefully) can link both parts together. A lot of C libraries already have headers which are compatible with C++, so this is a common procedure.
(*): Some header files are already made to be compatible with both languages C and C++ by using the common subset of language features plus wrapping everything in a conditional extern "C" block. For such headers, you should not use this method, but only for the ones which don't have such a block in it.

C code compiled with C++: undefined reference

I have a small program that I can compile with GCC and ICC without any difficulties, but I would also like the code to work with G++ and ICPC. I tried to add this:
#ifdef __cplusplus
extern "C" {
#endif
at the beginning and this:
#ifdef __cplusplus
}
#endif
at the end of all the header files, but I still get several `undefined reference to "..."' errors.
I think you're getting it wrong... The extern C is for disabling the function mangling; so if you do it just for the header files, when you try to link your mangled object code, the declared function names won't match with the function names in the object file.
Anyway, the extern C won't add any portability if the whole application is being compiled and linked with the same C++ compiler, it's intended for mixing C libraries with C++ code.
If your code is in the common subset of C and C++, you should be already able to compile it with either compiler, but I cannot see the reason to do that (besides working on the principle of least surprise, as C++ is more strict with some things).
You get undefined references because the declaration and the definition are not matching if you put extern "C", which prevents name mangling from happening: but in this case this is happening only in your header files.
If one of the undefined references is gxx_personality, then I'd say the post by "fortran" is correct.
See my response to this earlier question: When to use extern "C" in simple words?
It should hopefully make it clear how to mix C and C++ code.