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

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

Related

g++ undefined reference to while linking with a custom shared library

I am trying to link my C++ program with a custom shared library. The shared library is written in C, however, I don't think that it should matter. My library is called libfoo.so. Its full path is /home/xyz/customlib/libfoo.so. I've also added /home/xyz/customlib to my LD_LIBRARY_PATH so ld should be able to find it. When I run nm -D libfoo.so, I get:
...
00000000000053a1 T myfunc
000000000000505f T foo
0000000000004ca9 T bar
00000000000051c6 T baz
000000000000527f T myfunc2
...
So I think that my library is correctly compiled. I am trying to link it my c++ file test.cpp by running
g++ -L/home/xyz/customlib -Og -g3 -ggdb -fsanitize=address test.cpp -o test -lfoo
However, I am getting the following errors:
/usr/bin/ld: in function sharedlib_test1()
/home/xyz/test.cpp:11: undefined reference to `myfunc()'
/usr/bin/ld: in function sharedlib_test2()
/home/xyz/test.cpp:33: undefined reference to `foo()'
...
What am I doing wrong? How can I resolve this? Note that I have renamed the files and the shared library as I cannot share the exact file and function names.
As indicated by the comments in the post, it turns out that I was missing the extern "C" in the header file. So in my code, I wrapped my include statement in an extern "C" which solved the issue.
TLDR: The header include in the code should look like:
extern "C" // Import C style functions
{
#include <foo.h>
}

How to compile with libquantum library

I'm currently learning this quantum computing C/C++ library called libquantum. After performing a successful installation and confirming it by trying some demos that came along the source code, I tried writing my own program (main.cpp).
#include<quantum.h>
int main(){
quantum_reg qr;
quantum_delete_qureg(&qr);
}
I tried to compile this program with:
g++ main.cpp -lquantum
but it failed:
/usr/bin/ld: /tmp/cc6aR9vu.o: in function main': main.cpp:(.text+0x23): undefined reference to quantum_delete_qureg(quantum_reg_struct*)' collect2: error: ld
returned 1 exit status
I also tried:
g++ main.cpp -L/usr/local/lib -lquantum
considering libquantum.so is there, but same error
What is happening here?
The library is C and seems to have no awareness of C++. The link error has a type in it, which suggests that the linker is trying to link it in C++ mode.
Try putting a extern "C" around the include:
extern "C" {
#include<quantum.h>
}
int main(){
quantum_reg qr;
quantum_delete_qureg(&qr);
}
What is going on? To implement function overloading, C++ encodes type information in function symbol names so they no longer match up with the C function names in the binary library, see https://en.wikipedia.org/wiki/Name_mangling

Symbol present in .so, compiled .o references it but link fails

I have a strange problem linking c++ with Leptonica. Normal function invocation works fine, but I need functions from the library which were originally not exposed in the .so library. So I have searched for the two interesting functions in the source, removed the static keyword, so they look similar to exposed ones. I have remade the full library after a make clean. The .so file looks OK:
nm liblept.so.5.0.0
...
000000000009d010 T dewarpGetMeanVerticals
000000000009d160 T dewarpGetTextlineCenters
000000000009d8f0 T dewarpIsLineCoverageValid
Compiling to .o file and observing it:
g++ -c -std=c++11 -I../leptonica/src/src/ preproc.cpp -L../leptonica/src/.libs/ -llept -o preproc
nm preproc
...
U dewarpGetMeanVerticals
U dewarpIsLineCoverageValid
While the same compiling without -c flag results in
/tmp/ccCPqS1R.o: In function `_dewarpGetTextlineCenters(Pix*, int)':
preproc.cpp:(.text+0x3d5): undefined reference to `dewarpGetMeanVerticals'
/tmp/ccCPqS1R.o: In function `_dewarpBuildPageModel(L_Dewarp*, char const*)':
preproc.cpp:(.text+0x81d): undefined reference to `dewarpIsLineCoverageValid'
collect2: error: ld returned 1 exit status
What do I do wrong?
Thank you in advance: Balázs
I think you may need the extern "C" keywords around those functions if you want to expose them in the so. Since the names don't appear to be mangled by the C++ compiler in the .so this is probably not the case.
I notice that you're showing us what's in liblept.so.5.0.0 and linking against liblept.so. Is it possible that you need to update a symbolic link so that you're linking against the correct .so file?

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

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.

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)