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

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.

Related

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

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.

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.

(Hidden?) MS Visual Studio settings affecting C/C++ compilation

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

Strange Eclipse C++ #define behaviour

(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;
}

Using C/C++ static libraries from iPhone ObjectiveC Apps

Is it possible to have a C static library API, which uses C++ internally and hide this from users of the library?
I have writen a portable C++ library I wish to statically link to an iPhone application.
I have created an Xcode project using the Max OS X 'static library' template, and copied the source across, as well as writing a C wapper (to deal with exceptions) using (extern "C").
I am trying to use the generated library (.a file) in another Cocoa iPhone application.
Everything works well if the I use (.mm) extentions on the calling ObjectiveC file and (.cpp) on the implementation class in the library.
But I get unresolved symbols on linking when I try and change the wrapper file to a (.c) extention, even though all the wrapper function files are only C functions.
Just becuase C++ is used internally in a library, does it mean that externally it still must be treated as a C++ program. Is there not anyway to enforce this abstraction?
Edit: Thanks for the replies,
I had been using extern "C", I was just unsure about what configurations where needed in the calling project. ie. if the calling projected would require to know if it used C++ or could be ignorant and think its a purely C library.
It would seem I cannot, and I must use (.mm) files on my ObjectiveC classes.
It's too hard to do this in comments, so I'm just going to demonstrate for you quickly what the linking issues are that you're having. When Xcode encounters files, it uses build rules based on the suffix to decide which compiler to use. By default, gcc links the files to the standard C library, but does not link with the standard C++ library. Archive files (static libraries) have no linking resolution done at all. They are basically an archive of object files which need to be linked. Since you have no .mm or .cpp files in your project, g++ is never called and your files are never linked to the standard libraries. To correct this, just add the standard C++ libraries to your other linker flags in your Xcode project, or just simply add them to the pre-defined other flags option as -l (e.g., -lstdc++).
Here is a quick demonstration:
stw.h:
#ifdef __cplusplus
extern "C"
#endif
void show_the_world(void);
stw.cpp:
#include <iostream>
#include "stw.h"
using namespace std;
extern "C" void show_the_world() {
cout << "Hello, world!\n";
}
Build the library:
$ g++ -c stw.cpp -o stw.cpp -O0 -g
$ ar rcs stw.a stw.o
Using the library from a C application:
myapp.c:
#include "stw.h"
int main() {
show_the_world();
return 0;
}
Building the C application:
$ gcc -o myapp myapp.c stw.a -lstdc++ -g -O0
$ ./myapp
Hello, world!
$
If you try to compile without the -lstdc++ you will get all the unresolved issues because the C compiler has absolutely NO idea that it should link to the C++ runtime (and why would it, right!?!?) so you have to add this manually. The other option you have is to change the build rule for your project... instead of having Xcode use gcc to build .c and .m files, tell it to use g++ and your issues will be resolved.
You should declare the functions you want to be visible extern "C". Their signatures need to be C-compatible, but the contents do not (you may access C++ objects, for instance, but you cannot pass them directly; pointers are okay). The symbols will then be visible to any C-compatible environment.
EDIT: And compile it as a C++ source file, C doesn't have the notion of language linkage. There are a couple other gotchas with language linkage (like the fact that all extern "C" functions with the same name are the same function, regardless of namespace).
EDIT2: In the header, you can check for the macro __cplusplus, and use that to set for C++ and other languages, respectively (because C++ will require extern "C" declarations, and other languages will probably complain about them).
Basically when you compile the C functions with a C++ compiler it mangles the function names and uses the C++ ABI.
When you use the *.cpp or *.mm extension you are using the C++ compiler.
What you want to do is force the compiler to generate C functions with un-mangles names and using the C ABI.
You can do this by either:
Compile with the C compiler.
Compile with the C++ compiler but make sure that you prefix the function declarations with extern "C"
A favorite way to set up the header file, so that the same file can be included from both C and C++ source files is:
#ifndef HEADER_GUARD_1_H
#define HEADER_GUARD_1_H
#ifdef __cplusplus
extern "C" {
#endif
// Declare C function interface here.
int myFunc(int x,char*);
#ifdef __cplusplus
}
#endif
#endif
thanks, for such good discussion.
what I did is:
1) I created a static lib using cocaotouch static lib option. In that i have c/c++/obj-c all mix. however, my exports are only obj-c classes.
Infact i used objc- to c to C++.
2) then I creatd iphone app in X-code proj.
I added the otherlink flags my lib name ( -lxyz ) //my lib name is libxyz.a
I added lib search path, header search path
3) then I compiled. I got errors.
saying oeprator new, operator delete not found.
3) then apart my appdelegate, view controller, I added
dummy cpp(.h, .cpp)...
atestdummy.h atestdummy.cpp
4) then I build again...
thats it worked.
So - I whatever suggestions they gave earlier workedfor me.
basic reason, unless u r app sees a .cpp file .mm file with cpp code,
linked will not use g++.
Thanks all.
I have read the above and ssolved my problem.
u guys are good to share.