954,492 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

g++ - linking error - undefined reference to <func_name>

Hi,

I have 3 seperate make file where,
1st one generates a static library libCanOpen.a,
(using ""ar -r ")
2nd one creates a dynamically linkable library libPixyCANopen.so
(using "g++ -Wall -fPIC -shared")
and the 3rd one creates the executable by linking it to libPixyCANopen.so.

The 1st two makefiles build without a single warning (-Wall is used)
The last Makefile is generating linking error like the following:

../lib/libPixyCANopen.so: undefined reference to `coTimerPulse'
../lib/libPixyCANopen.so: undefined reference to `releaseTimer'


nm command shows that the corresponding object names are mangled (e.g. _Z12releaseTimerv), Using extern "C" in the header file did not remove it.

But, I am using g++ for every compilation, so I think the mangling should not matter.

Any suggestion is appreciated.

Thanks,
Anirban

anirbanjoy
Newbie Poster
4 posts since Jun 2009
Reputation Points: 10
Solved Threads: 0
 

> nm command shows that the corresponding object names are mangled (e.g. _Z12releaseTimerv),
Try adding the extern "C" to the implementation of those functions as well.

> Using extern "C" in the header file did not remove it.
But it did make it so that the users of that function did get the unmangled name.

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 

Thanks .. that did help ..

There is only one linking error now, it's an extern variable .. the problem is same .. "undefined reference to " ..

Need to share this variable .. that means I have to keep that extern stuff .. but, how?

anirbanjoy
Newbie Poster
4 posts since Jun 2009
Reputation Points: 10
Solved Threads: 0
 

Thanks .. that did help ..

There is only one linking error now, it's an extern variable .. the problem is same .. "undefined reference to " ..

Need to share this variable .. that means I have to keep that extern stuff .. but, how?

The short answer to that one is that you should not have public access to the variable, access should be wrapped within get/set methods.

And you shouldn't have to worry about name-mangling, declaring functions as extern C isn't necessary. What do your makefiles look like?

Stinomus
Junior Poster
110 posts since May 2009
Reputation Points: 58
Solved Threads: 17
 

It's shouldn't be necessary to use extern,
generally you have access to all the public variables and function in the symboltable, but only the externed are required to have the same signature, from version to version.
This is atleast how it should be.

http://people.redhat.com/drepper/dsohowto.pdf

try doing a ldd on your compiled files to see if anything is missing

monkey_king
Junior Poster
160 posts since Aug 2008
Reputation Points: 70
Solved Threads: 9
 

This was my assumption too. As I am using g++ for all the cmpilation, extern "C" stuff does not seem logical. however, here are the outputs of 3 Makefiles in order:

Makefile #1

root:/tmp/trunk/CANopenStack/source# make CC=g++
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o access_o.o access_o.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o cmsmain.o cmsmain.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o nmt.o nmt.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o cmscodec.o cmscodec.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o sdoserv.o sdoserv.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o sdoclien.o sdoclien.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o sdomain.o sdomain.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o sdo.o sdo.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o emerg.o emerg.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o lme.o lme.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o pdo.o pdo.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o set_com.o set_com.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o sync.o sync.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o utility.o utility.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o time.o time.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o timer.o timer.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o nmterr.o nmterr.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o nmt_s.o nmt_s.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o led.o led.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o co_debug.o co_debug.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o heartbt.o heartbt.c
g++ -Wall -I/tmp/trunk/PIXYapi/include -I/tmp/trunk/PIXYapi -I../include -I. -I/tmp/trunk/CANdriver/include   -c -o slave_ut.o slave_ut.c
ar -r ./lib/libCanOpen.a access_o.o cmsmain.o nmt.o cmscodec.o sdoserv.o sdoclien.o sdomain.o sdo.o emerg.o lme.o pdo.o set_com.o sync.o utility.o time.o timer.o nmterr.o nmt_s.o led.o co_debug.o heartbt.o slave_ut.o
ar: creating ./lib/libCanOpen.a


Makefile #2

root:/tmp/trunk/PIXYapi# make CC=g++
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o ../CANdriver/src/can_p_l.o ../CANdriver/src/can_p_l.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o ../CANdriver/src/cpu_generic.o ../CANdriver/src/cpu_generic.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o ../CANdriver/src/cdriver.o ../CANdriver/src/cdriver.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o ../CANdriver/src/cpu.o ../CANdriver/src/cpu.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o co_init.o co_init.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o nmtslave.o nmtslave.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o objects.o objects.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o usr_301.o usr_301.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include   -c -o PixyCANopen.o PixyCANopen.c
g++ -Wall -fPIC -shared -DNO_RT -I. -I./include -I../CANopenStack/include -I../CANdriver/include -shared -o lib/libPixyCANopen.so ../CANdriver/src/can_p_l.o ../CANdriver/src/cpu_generic.o ../CANdriver/src/cdriver.o ../CANdriver/src/cpu.o co_init.o nmtslave.o objects.o usr_301.o PixyCANopen.o -L../CANopenStack/source/lib/ -L./lib -lpcan -lCanOpen -lh8com


Makefile #3

root:/tmp/trunk/PIXYapi/test# make
g++ -g -Wall -DNO_RT -I../include/ -I../ -I../../CANopenStack/include/ -I../../CANdriver/include/ -I../CANopenStack/source   -c -o src/main.o src/main.cpp
g++ -g -Wall -DNO_RT -I../include/ -I../ -I../../CANopenStack/include/ -I../../CANdriver/include/ -I../CANopenStack/source -L../lib -lPixyCANopen -o ApiTest src/main.o 
../lib/libPixyCANopen.so: undefined reference to `coTimerPulse'


Existence of coTimerPulse in code is:

root:/tmp/trunk# grep -nR "coTimerPulse" *
CANdriver/src/.svn/text-base/cpu_generic.c.svn-base:164:VOLATILE UNSIGNED16 CO_CONST coTimerPulse = CONFIG_TIMER_INC; /**< length of 1 tick / unit 100us */
CANdriver/src/cpu_generic.c:169:UNSIGNED16 CO_CONST coTimerPulse = CONFIG_TIMER_INC; /**< length of 1 tick / unit 100us */
CANopenStack/include/co_drv.h:149:extern UNSIGNED16 coTimerPulse;
CANopenStack/include/co_drv.h:151:extern UNSIGNED16 CO_CONST coTimerPulse;
Binary file CANopenStack/source/timer.o matches
CANopenStack/source/lme.c:533:    GL_VAR(coTimerPulse) = CONFIG_TIMER_INC;
Binary file CANopenStack/source/lib/libCanOpen.a matches
CANopenStack/source/globvars.c:261://UNSIGNED16 coTimerPulse;
CANopenStack/source/timer.c:565:    if (timerVal > ((UNSIGNED32)GL_VAR(coTimerPulse) << 15))  {
CANopenStack/source/timer.c:573:    if ((timerVal + pTimer->restTime) <= GL_VAR(coTimerPulse))  {
CANopenStack/source/timer.c:580:        pTimer->endTime = tVal / GL_VAR(coTimerPulse);
CANopenStack/source/timer.c:582:        pTimer->endTime = (UNSIGNED16)(tVal / GL_VAR(coTimerPulse));
CANopenStack/source/timer.c:585:        pTimer->restTime = (UNSIGNED16)(tVal % GL_VAR(coTimerPulse));
CANopenStack/source/timer.c:744:        retVal = addTimerEvent(pTimer, pTimer->endTime * GL_VAR(coTimerPulse),
CANopenStack/source/timer.c:829:    ticks = timerVal / GL_VAR(coTimerPulse);
CANopenStack/source/timer.c:831:    if ((ticks * GL_VAR(coTimerPulse)) < timerVal)  {
GL_VAR(coTimerPulse) = CONFIG_TIMER_INC;
Binary file PIXYapi/test/lib/libPixyCANopen.so matches
Binary file PIXYapi/lib/libPixyCANopen.so matches

It's shouldn't be necessary to use extern, generally you have access to all the public variables and function in the symboltable, but only the externed are required to have the same signature, from version to version. This is atleast how it should be.

http://people.redhat.com/drepper/dsohowto.pdf

try doing a ldd on your compiled files to see if anything is missing

anirbanjoy
Newbie Poster
4 posts since Jun 2009
Reputation Points: 10
Solved Threads: 0
 

Could you try doing a
'ldd libPixyCANopen.so'

monkey_king
Junior Poster
160 posts since Aug 2008
Reputation Points: 70
Solved Threads: 9
 

root:/tmp/trunk/PIXYapi/lib# ldd libPixyCANopen.so
libpcan.so.0 => /usr/lib/libpcan.so.0 (0x00138000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0013b000)
libm.so.6 => /lib/libm.so.6 (0x0021c000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00241000)
libc.so.6 => /lib/libc.so.6 (0x0024c000)
/lib/ld-linux.so.2 (0xb7f07000)$

I removed the extern variable and now the linking problem is gone .. but still I will keep trying to remove the extern "C" completely from my code.

Could you try doing a 'ldd libPixyCANopen.so'
anirbanjoy
Newbie Poster
4 posts since Jun 2009
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You