g++ linking issue - c++

I have a dependancy library (libfcgi) that I compiled with g++ (GCC v4.4 MinGW) using the following calls:
g++ -Iinclude -c -O2 *.c
ar rcs ../libfcgi.a *.o
Now, my main project is built like so:
g++ -Idependancies\libfcgi\include -Ldependancies -O2 -lfcgi *.cpp
g++ apparently finds libfcgi.a, but yet it fails to link to the following references:
'FCGI_printf'
'FCGI_Accept'
In the libfcgi sources, these functions are defined as follows:
#ifdef __cplusplus
extern "C" {
#endif
//...
DLLAPI int FCGI_printf(const char *format, ...);
DLLAPI int FCGI_Accept(void);
//...
#ifdef __cplusplus
}
#endif
where DLLAPI is nothing (as it isn't compiled as a shared library) and __cplusplus is defined (g++).
Looking at libfcgi.a, those functions are exported as '_FCGI_Accept' and '_FCGI_printf', so with an underscore in front. That's what seems to hinder g++ to find them.
I thought using export "C" would suffice to link to a C function in C++, so what am I doing wrong?
Thanks :)

If you have the same extern "C" definitions in your .cpp sources, then I think your problem is that the -lfcgi should follow the *.cpp in your command line:
g++ -Idependancies\libfcgi\include -Ldependancies -O2 *.cpp -lfcgi

In your main-project, you tell the compiler to link C-functions, due to the extern "C". It therefore expects unmangled symbol-names. You should therefore compile the fcgi-library with the C compiler, not the C++ compiler.

Related

How to use C++ function from header in C?

I'm writing my thesis and I have problem with using C++ function in C code. I searched solution and I found a lot of them, but it didn't work anyway. Please explain it to me one more time.
To be quick I have something like below and after gcc main.c -o main I get undefined reference to 'cppfun'
cpp.h:
#pragma once
#ifdef __cplusplus
extern "C" {
#endi
void cppfun();
#ifdef __cplusplus
}
#endif
cpp.cpp:
#include <stdio.h>
#include "cpp.h"
void cppfun()
{
printf("cpp_fun");
}
main.c:
#include <stdio.h>
#indlude "cpp.h"
int main(int argc, char *argv[])
{
cppfun();
return 0;
}
When you combine C and C++, you should compile the translation unit containing the main function, as C++. Not opposite. This is a FAQ.
An undefined reference is usually because you haven't linked in the translation unit where the missing thing is. Your stated build command is
gcc main.c -o main
while it should be e.g.
gcc -c main.c
g++ -c cpp.cpp
g++ cpp.o main.o -o main
except as mentioned, the main translation unit should be in C++.
You need to include all .cpp files after main. Something like that:
g++ main.cpp other.cpp etc.cpp -o main
Firstly you compile your cpp code without link via -c compiler switch
g++ cpp.cpp -c
and you have cpp.o file then compile and link your main.c with cpp.h and cpp.o files via gcc
gcc main.c -o main cpp.o
I tested this answer via my linux server. It is work.

Linking my program using g++

I have some problems to build a program using g++. The program is using a library that I have written in C called libiec60063. I want to write my new project in C++ (even if not yet familiar with C++) but I can't manage to link it correctly.
For example I have the following code in a file called main.cpp
#include <libiec60063.h>
int main() {
Select_IEC60063_Number(125, 12);
return 0;
}
I can compile the source correctly typing
g++ -I/home/workspace/a_CommonBinary/include -c main.cpp
If I want to link it i get some error message
g++ -L/home/workspace/a_CommonBinary_draft/lib -o main main.o -lm -liec60063
main.o: In function `main':
main.cpp:(.text+0x1b): undefined reference to `Select_IEC60063_Number(double, int)'
collect2: error: ld returned 1 exit status
If I rename the main-file to main.c I can compile and link the program correctly with the GCC-Compiler using the same parameters.
Can anybody explain where there is a difference between gcc and g++?
You probably forgot to put
#ifdef __cplusplus
extern "C" {
#endif
near the beginning of your libiec60063.h header file, and
#ifdef __cplusplus
}; // end extern "C"
#endif
near the end of your header file, or if you don't want to change the header file:
extern "C" {
#include <libiec60063.h>
};
in your C++ code.
See this question. You need to disable name mangling. Read about compatibility of C & C++ .
BTW, you should compile with g++ -Wall -Wextra -g and perhaps with -std=c++11 and code for C++11

Linker error in switching from cc compiler to g++ compiler

I have been using C to code for sometime and I had no issues in compiling and linking my code to archive libraries (.a files). However, now I need to switch to C++ and doing so, I have to use g++ instead of cc for linking and compiling.
Using C, first thing to do was compiling the source and creating the object file and then linking it to the library using the same command but without the -c option:
cc -c -ggdb -Wall -Werror -I.. test.c -o test.o
cc -o test -ggdb -Wall -Werror test.o ../libpmem/libpmem.a
As I think the same procedure should be done for doing the same thing with g++, I tried to change the compiling and linking phase as follow:
g++ -c -ggdb -Wall -Werror -I.. test.c -o test.o
g++ test.o -I.. -L/path/libpmem -lpmem -o test
Although both sets should do the same thing, I always get an error while trying to link using g++. Here is the error message:
test.o: In function `main':
/path/test/test.c:5: undefined reference to `pmem_msync_mode()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
There must be something wrong with the linking phase as the method definition must be found in the library file (just as the cc linker can find the definition and do the linking without any problem).
I also tried to do both linking and compiling using a single g++ command, but no matter what I do, I always get the same error. Any idea how can I fix this?
you probably have some sort of name mangling problem...
since it looks like that is declared in a c library there should already be some sort of
#ifdef __cplusplus
extern "C" {
#endif
int pmem_msync_mode();
#ifdef __cplusplus
}
#endif
but if there isn't in the library header you may have to do something like;
extern "C" {
#include <pmem.h>
}
See http://www.cplusplus.com/forum/general/1143/
You need to tell the compiler that the code is compiled as C
I am assuming that the pmem library is compiled and linked as C code.
C and C++ have different conventions for how they store the names of functions in binary format. See http://en.wikipedia.org/wiki/Name_mangling for a reference.
To solve your problem, probably the solution is to:
extern "C" {
#include <pmem.h>
}
When the C++ compiler imports the function declarations from the header, without external C linkage being specified, it expects the binary it links against to have the associated functions' representations in a different format, namely whatever format your C++ compiler mangles function names to.

Can I mix c and cpp files in a C++ project?

I have a project that had c files and cpp files mixed in it. The linker throws errors at me:
undefined reference to <all my functions in the c files>
After I rename all *.c files to *.cpp the errors vanish. So can't I mix those files or is this some compiler/linker options problem?
My options:
GCC C++ Compiler:
-I/usr/include/glib-2.0 -I/usr/include/gtk-2.0 -I"/myPath" -O0 -g3 \
-Wall -c -fmessage-length=0 `pkg-config --cflags glib-2.0 gtk+-2.0
GCC C Compiler:
-I/usr/include/glib-2.0 -I/usr/include/gtk-2.0 -I"/myPath" -O0 -g3 \
-Wall -c -fmessage-length=0 -std=c99 `pkg-config --cflags glib-2.0 gtk+-2.0`
GCC C++ Linker:
-L/usr/include/glib-2.0/glib `pkg-config --libs gtk+-2.0`
Since it says C++ Linker, does that mean object files from c files cannot be linked into the project (by default)?
You need to wrap the C code like so
extern "C" {
#include "sample1.h"
}
A better way to do it is like in this StackOverflow question, in the C header files.
use:
#ifdef __cplusplus
extern "C" {
#endif
At the start of all C header files.
and use:
#ifdef __cplusplus
}
#endif
At the end of all C header files.
extern "C" is one approach. The other approach, assuming your C files are of the (almost ubiquitous) sort which are already compilable as C++, is simply to coerce the compiler into treating them as C++ (which gives them the appropriate name mangling to work with your C++ files). For GCC, this is -x c++.

Linking C from C++ in OS X Mavericks

Having transitioned to OS X Mavericks and XCode 5.0.1, I can no longer gracefully link compiled C files (output from gcc) to a C++ project (output from g++).
The offending pair of commands produced from my makefile are:
gcc `pkg-config --cflags glib-2.0` -g -Wall -O3 `pkg-config --cflags flann` -c -o vec.o vec.c
g++ `pkg-config --cflags glib-2.0` -g -Wall -O3 -stdlib=libstdc++ -lstdc++ layoutquality.cpp vec.o `pkg-config --libs glib-2.0` -L/usr/local/Cellar/flann/1.8.4/lib -lflann -o layoutquality
To which the linker complains:
Undefined symbols for architecture x86_64:
"load_dmat(char const*)", referenced from:
_main in layoutquality-I8HOqy.o
ld: symbol(s) not found for architecture x86_64
Where load_dmat is just a function in the file vec.c . If I replace the gcc with g++ in the first line, then everything compiles and links fine, but clang says:
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
Is there an inoffensive, non-deprecated way of compiling and linking these? Linking with g++ together with object files from gcc worked fine before I upgraded to OS X Mavericks and the new command line tools. Any insight into what changed and how to go forward would be great, thanks.
Adding a "-x c" (without quotes) before "vec.c" should fix it.
If you compile multiple .c/.cpp files in the same line you can use "-x c" or "-x c++" before each list of C or C++ filenames to switch context appropriately. For example:
g++ -x c alpha.c beta.c -x c++ gamma.cpp
Here's an example Makefile that let us use C++ code/function in a C program.
CC=clang
CXX=clang++
CFLAGS=-Wall -g
CXXFLAGS=-Wall -g -std=c++11 -I.
DEPS=CPP.h
OBJ=main.o CPP.o
RM=rm -f
# compile only, C source
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
# compile only, C++ source
%.o: %.cpp $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
# link
main: $(OBJ)
$(CXX) -o $# $^ $(CXXFLAGS)
clean:
$(RM) $(OBJ)
As you can see, we generate our objects separately using CXXFLAGS and CFLAGS in two separate calls to the compiler. In the context of Mac using Xcode's clang, clang (CC) and clang++ (CXX) are actually the same thing. Only the differing flags matter. I am just being pedantic by stating the definitions of CC and CXX in the above example Makefile.
Once the object files are generated, we are good to go to link them together.
Note however that you have to do one extra step to make your C++ code usable by the C program.
In CPP.h in this example, you have to explicitly use extern "C" to specify linkage for your C++ code for use by C.
For example, like this:
#ifdef __cplusplus
extern "C" {
#endif
double timesTwo(double number);
#ifdef __cplusplus
}
#endif
The preprocessor macros #ifdef __cplusplus and #endif are to make sure that our header file won't cause C-mode compilation errors and is only in-effect during C++-mode compilation.
This complete example comprises only 4 files.
Makefile
main.c
CPP.h
CPP.cpp
The Makefile source and CPP.h are explained above.
For a complete understanding, I am including main.c and CPP.cpp here as well.
main.c:
#include <stdio.h>
#include "CPP.h"
int main()
{
printf("Running main.c\n");
double ans = timesTwo(3.0);
printf("The answer from our C++ timesTwo function, when given 3.0, is %f\n", ans);
return 0;
}
CPP.cpp:
#include "CPP.h"
double timesTwo(double number)
{
return 2 * number;
}
I trust that this explanation and example clarifies how we can set up our Makefile, specify the #ifdef __cplusplus preprocessor macro and extern "C" linkage declaration to allow C++-to-C interop, and with no erroneous clang warning when we run make.
Most probably you are a victim of Name mangling. To avoid name mangling in C++, use extern "C" around declarations, like:
#ifdef __cplusplus
extern "C" {
#endif
void load_dmat(char const*);
#ifdef __cplusplus
}
#endif