Linking problems with g++, but not with cc [duplicate] - c++

This question already has answers here:
How to resolve the linker error in C++ compiler
(3 answers)
Closed 9 years ago.
I'm using 64-bit CentOS version of Linux. I'm trying to create and use a static library (libUtility.a) in my C and C++ programs. I can compile the library with C, and produce the libUtility.a file with ar. Then I try to link it into my program. Everything works when I use the C compiler
cc myprog.c -o myprog -I/usr/local/include -L/LocationOfMyLib -lUtility
However, when I use the g++ compiler, I receive the errors.
g++ myprog.c -o myprog -I/usr/local/include -L/LocationOfMyLib -lUtility
myprog.c: In function 'int main(int, char**)':
/tmp/cckIN1Yk.o: In function `main':
myprog.c:(.text+0x41): undefined reference to `Utility_HiWorld(char*)'
collect2: ld returned 1 exit status
I have moderate experience in C and C++, but no experience creating my own
libraries. This library only has one subroutine named Utility_HiWorld(). And myprog.c only calls that one subroutine. What am I doing wrong in here?
NEW: Okay, I definitely didn't use 'extern "C"'. I didn't even know what that was. That solved it.

I would guess that you are failed to tell your C++ compiler that the external function is written in C.
Since you want to use the library from C and C++ you need to do something like this in your libraries header file.
#ifdef __cplusplus
extern "C" {
#endif
void Utility_HiWorld(char*);
#ifdef __cplusplus
}
#endif
__cplusplus is only defined for a C++ programs, so a C++ program will see extern "C" { ... } which is what it needs to tell it that Utility_HiWorld is a C function.
See here for more details.
Just a guess, post some code if you think the problem is something else.

Related

C/C++ linking issue with a very simple setup [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
I'm getting an "undefined reference" error when trying to compile and link a very simple app that has a dependency on a third-party library.
My main.c looks like this:
#include "ss7cp.h"
/*
extern "C" {
void EINSS7CpMain_CpInit(void);
}
*/
int main() {
EINSS7CpMain_CpInit();
}
The third-party header file has:
#if defined (__cplusplus) || defined (c_plusplus)
extern "C" {
#endif
...
void EINSS7CpMain_CpInit(void);
The definition of this function is in an archive:
$ nm -g /path/to/lib/libsign_64_uthr.a | grep EINSS7CpMain_CpInit
0000000000005ae0 T EINSS7CpMain_CpInit
U EINSS7CpMain_CpInit
U EINSS7CpMain_CpInit
By the "T" above, the function must be defined in the text/code section of one of the libs in the archive.
I'm currently not using a Makefile, but just trying to quickly build this simple app entirely from the command line:
g++ -I/path/to/include -L/path/to/lib -lsign_64_uthr -D__EXTENSIONS__ -DLINUX main.c
(The documentation told me to define both __EXTENSIONS__ and LINUX). The rest of the above is pretty straightforward. What I'm getting is:
/tmp/ccvgmIJ8.o: In function `main':
main.c:(.text+0x5): undefined reference to `EINSS7CpMain_CpInit'
collect2: error: ld returned 1 exit status
I've tried both as a C file (main.c) and C++ file (main.cpp, enabling the extern "C" block), but no difference. (Can I assume g++ decides on C versus C++ just by the file extension?)
I've even just compiled the file (with -c) and took a look at the contents of the resultant main.o object file and saw the text "EINSS7CpMain_CpInit" as it is, unmangled (or maybe that's just a debug symbol?)
What are some diagnostics steps I can take to see what I'm missing? Do I actually need to create a Makefile and split the compile and link steps?
It's been ages since I last did any C/C++ and even back when I did it, I usually wasn't the one who had to create the Makefiles from scratch, so I'm probably missing some very fundamental stuff here...
My best guess would be parameter ordering, the lib should come after the source file:
g++ -I/path/to/include -D__EXTENSIONS__ -DLINUX main.c -L/path/to/lib -lsign_64_uthr

undefined reference error for g++ but not for gcc when using BSP library

I am making a parallel program for one of my courses. Now initially it was written in C and it all worked just fine. Then we changed it all to c++ and all of a sudden I get some error when I try to compile the program. I am using the package mcbsp (Multicore BSP) for the parallel part. Here is the program
#include <stdio.h>
#include <stdlib.h>
#include <mcbsp.h>
void sieve(){
return ;
}
main(int argc, int **arhv){
bsp_begin(5);
printf("%d\n",bsp_pid());
bsp_end();
return 0;
}
So I make a file aaa.c and aaa.cpp both with this content. Then when I type in the terminal
gcc aaa.c -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it compiles just fine and the program does as expected (print the id of the cores). However, when I type
g++ aaa.cpp -MMD -g -I../bsp/include -L../bsp/lib -lmcbsp1.2.0 -lpthread
it gives the following feedback
/tmp/ccH3uox9.o: In function `main':
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:10: undefined reference to `bsp_begin(unsigned int)'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:11: undefined reference to `bsp_pid()'
/home/teun/Documents/C/BSP/Sieve/sieve/aaa.cpp:12: undefined reference to `bsp_end()'
collect2: error: ld returned 1 exit status
I have been stuck with this for about an hour now and it is really getting frustrating. I must admit that I have little experience in programming in c++ as I mostly use C. Does anyone know what is going wrong?
EDIT: The program I displayed is just a small working example that uses the BSP functionality.
The simple declaration int bsp_end(); is interpreted differently in C and C++. The reason is that in C++, you can overload functions, which requires that their parameters are included in the symbol name for the linker, see C++ name mangling for further info. Now, since the function is compiled with a C compiler but the declaration is given to a C++ compiler, the symbols don't match and you get linker errors.
As a solution, add extern "C" to the function declaration or maybe wrap the whole include:
extern "C" {
#include <mcbsp.h>
}
You need extern "C" around #include
extern " C" {
#include "c-header.h"
};
This is needed to stop the C++ name mangling

undefined reference to a function c [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
This question maybe have been asked before. I could not find it to the best of my searches.
I'm trying to link libpfm4.5.0 in my code. The header file that I'm using is the following: perf_util.h
Here is the link to download libpfm4.5.0.
Does it matter where exactly I include the header file?
Here is a snippet of my code:
#include "matrix.h"
#include "perf_util.h"
int read_counts(int pid, int app_num){
int ret, i, num_fds = 0, grp, group_fd;
int ready[2], go[2];
char buf;
int nevents;
nevents = TOTAL_NUM_EVENTS;
go[0]=go[1] = -1;
for (grp = 0; grp < nevents; grp++) {
int ret;
ret = perf_setup_list_events(perf_events.pmc[grp], &fds_pid[app_num], &num_fds);
if (ret || !nevents)
exit(1);
}
}
the header file perf_util.h does contain perf_setup_list_events function but during compilation
matrix.o: In function `read_counts(int, int)':
matrix.c:(.text+0xf20): undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'
collect2: error: ld returned 1 exit status
This is the error I get. What could be the possible places I would have done the error? Any help would be appreciated.
This is how I compile.
g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c
g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o /libpfm-4.5.0/perf_examples/../lib/libpfm.a
Note: libpfm compiles using cc and I use g++. Could that be the problem? if yes, how should I solve it?
Here is how I compile it now:
cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c
cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o libpfm-4.5.0/perf_examples/../lib/libpfm.a
error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token
const char * pmc[TOTAL_NUM_EVENTS] = {"blah", "blahbar"}
I've a const char * array and this is the error I get.
OK, so, contrary to what I thought at first, your program is a C++ program. We know this is the case because the C++ compiler accepts it and the C compiler doesn't. (You still haven't given enough information for me to understand why the C compiler doesn't like it, but I suspect it's something uninteresting like defining a file-scope variable that can't be fully initialized at compile time. If you meant this to be a C program you should ask a new question about that. Anyway.)
The library you are using is C, not C++, and its header files are not set up to be used from C++ programs. I deduced that this was the problem from the error message:
undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'
See how that error message gives a full prototype for the function perf_setup_list_events? That's because C++ has function overloading and C doesn't -- so, in C++, every function is given a "mangled name" which encodes its prototype. If you do nm matrix.o | grep perf_setup_list_events you will discover this mangled name: it's probably something like _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi. The linker is helpfully decoding that again to a prototype.
So, the fact that the linker error has a full prototype, all by itself, tells me that the undefined reference is from code compiled as C++. Now, I have never heard of libpfm4.5.0 before, but I do know that you would have gotten a different error message if your library didn't actually define that function -- something like
error: ‘perf_setup_list_events’ was not declared in this scope
So I guessed that the library is written in C, not C++, and that its header files are not written to handle being used from C++ programs. This is a defect in the library, but one that can be worked around by writing
extern "C" {
#include "perf_util.h"
}
instead of just the bare #include. The extern "C" { ... } construct tells a C++ compiler to not apply name mangling to whatever is declared within. Thus, your program, when compiled that way, looks for a symbol named perf_setup_list_events instead of _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi and it links successfully.

Link dynamic shared library in Linux - Undefined reference to function

I know there are many questions related to shared libraries on Linux but maybe because I'm tired of having a hard day trying to create a simple dynamic library on Linux (on Windows it would have taken less than 10 minutes) I can't find what happens in this case.
So, I am trying to create a library to be linked at build-time and used at run-time (not a static library, not a library to be embedded into the executable, in other words). For now it contains a simple function. These are my files:
1.
// gugulibrary.cpp
// This is where my function is doing its job
#include "gugulibrary.h"
namespace GuGu {
void SayHello() {
puts("Hello!");
}
}
2.
// gugulibrary.h
// This is where I declare my shared functions
#include <stdio.h>
namespace Gugu {
void SayHello();
}
3.
// guguapp.cpp
// This is the executable using the library
#include "gugulibrary.h"
int main() {
GuGu::SayHello();
return 0;
}
This is how I try to build my project (and I think this is what is wrong):
gcc -Wall -s -O2 -fPIC -c gugulibrary.cpp -o gugulibrary.o
ld -shared -o bin/libGugu.so gugulibrary.o
gcc -Wall -s -O2 guguapp.cpp -o bin/GuGu -ldl
export LD_LIBRARY_PATH=bin
This is saved as a .sh file which I click and execute in a terminal. The error I get when trying to link the library is this:
/tmp/ccG05CQD.o: In function `main':
guguapp.cpp:(.text.startup+0x7): undefined reference to `SayHello'
collect2: ld returned 1 exit status
And this is where I am lost. I want the library to sit in the same folder as the executable for now and maybe I need some symbols/definitions file or something, which I don't know how to create.
Thanks for your help!
In your C++ file, GuGu::SayHello is declared as a C++ symbol. In your header, you are wrapping it in an extern "C" block. This is actually undefined, as you aren't allowed to use C++ syntax (namespace) in that context. But my guess is that what the compiler is doing is ignoring the namespace and generating a C symbol name of "SayHello". Obviously such a function was never defined by your library. Take out the extern "C" bits, because your API as defined cannot be used from C anyway.
You are inconsistent with your GuGu, there are also Gugu's running around, this needs to be made consistent, then it works (At least on my computer are some Gugu's now)

How to link a C++ shared library with gcc

I have seen a GCC link with a C++ shared library, but I am not able to reproduce it on my own. So first I create a C++ library with a testfunction:
g++ -shared -o libtest.so test.c
Then I have a test main function which calls the library function and compile it like this
gcc -o prog.out main.c -L. -ltest
Then i receive the error
undefined reference to 'testfunc'
which i think is caused by different refernce in the library ... C names the function testfunc and C++ names the function [some stuff]__testfunc[maybe again some stuff].
I have also tried to use
gcc -o prog.out main.c -l:libtest.so
but this results in the same error.
Therefore, my question is: How is it possible to link a c++ library with gcc to a c file?
Update: I know i can use extern "C", but that's not the way it is solved. Maybe there are some parameters for the linker instead?
Update2: Just thought it could also be possible that the first part is just compiled with c++ and linked with gcc. Also tried this:
g++ -c testlib.c -o testlib.o
gcc -shared -o libtest.so testlib.o
gcc -o prog.out -l:libtest.so
still doesn't work. Is there something wrong with the flags?
Yes, the problem has nothing to do with shared libraries (I think...) and everything to do with name mangling.
In your header, you must declare the function like this:
#ifdef __cplusplus
extern "C" {
#endif
void testfunc(void);
#ifdef __cplusplus
}
#endif
This will cause testfunc to have the same symbol and calling conventions for both C and C++.
On the system I'm using right now, the C symbol name will be _testfunc and the C++ symbol name (assuming you don't use extern "C") will be __Z8testfuncv, which encodes information about the parameter types so overloading will work correctly. For example, void testfunc(int x) becomes __Z8testfunci, which doesn't collide with __Z8testfuncv.
When you use g++ it compiles ALL source as C++. This means all function use the C++ ABI (this also including name mangling). When you use gcc it compiles *.c files using the C ABI (no name mangling).
Thus the same function compiles with the two different compilers will generate different functions (in a lot of ways). That's because they are different languages.
To force g++ to compile a function using the C ABI prefix it with extern "C"
extern "C" void testfunc(char*);
Alternatively use the block version
extern "C" {
<multiple Functions>
}
To be honest I never compile anything with gcc anymore (unless there is some hard requirement to do so (in which case I usually fix the code so it works in C++)). If you compile all files with g++ just makes the processes simpler.
If you are sure it's not because of name mangling. Then it means gcc could not find the library try giving the full path of the library unless the .so file is in standard location. If you are not sure then recheck for any conflict in variable (function) name. Use namespaces to group classes and define the functions inside the classes to avoid naming conflict