20

I tried to link a static library (compiled with gcc) to a c++ program and I got 'undefined reference'. I used gcc and g++ version 4.6.3 on a ubuntu 12.04 server machine. For example, here is the simple library file for factorial method:

mylib.h

#ifndef __MYLIB_H_ #define __MYLIB_H_ int factorial(int n); #endif 

mylib.c

#include "mylib.h" int factorial(int n) { return ((n>=1)?(n*factorial(n-1)):1); } 

I created object for this mylib.c using gcc:

gcc -o mylib.o -c mylib.c 

Again the static library was created from the object file using AR utility:

ar -cvq libfact.a mylib.o 

I tested this library with a C program (test.c) and C++ program (test.cpp)

Both C and C++ program have the same body:

#include "mylib.h" int main() { int fact = factorial(5); return 0; } 

Assuming static library libfact.a is available in /home/test directory, I compiled my C program without any issues:

gcc test.c -L/home/test -lfact 

However while testing C++ program, it threw a link error:

g++ test.cpp -L/home/test -lfact test.cpp:(.text+0x2f): undefined reference to `factorial(int)' collect2: ld returned 1 exit status 

I even tried adding extern command in test.cpp:

extern int factorial(int n) //added just before the main () function 

Still the same error.

  • Can someone tell me what I am wrong here?
  • Is there anything I missed while creating the static library?
  • Do I have to add anything in my test.cpp to make it work?
1
  • 1
    When I see SO questions with no upvote, along with a 7-upvoted answer, I fully understand how foolish humanity is. How can the answer be relevant if the question is not? Come on! Commented Jun 4, 2014 at 19:01

2 Answers 2

29

The problem is that you haven't told your C++ program that factorial is written in C. You need to change your test.h header file. Like this

#ifndef __MYLIB_H_ #define __MYLIB_H_ #ifdef __cplusplus extern "C" { #endif int factorial(int n); #ifdef __cplusplus } #endif #endif 

Now your header file should work for both C and C++ programs. See here for details.

BTW names containing a double underscore are reserved for the compliler (so are names starting with an underscore and a capital letter) so #ifndef __MYLIB_H_ is illegal strictly speaking. I would change to #ifndef MYLIB_H #define MYLIB_H

Sign up to request clarification or add additional context in comments.

2 Comments

Yes it works like charm with this. Thanks for the link. Thanks for adding info about double underscore.
great explanation. +1
1

While the accepted answer is absolutely correct, I thought I'd just add an observation. Some editors have trouble with the open / close brace, and will indent the entire extern "C" scope in the header. If mylib.h is a key header for a library, you might consider:

#if defined (__cplusplus) #define _MYLIB_INIT_DECL extern "C" { #define _MYLIB_FINI_DECL } #else #define _MYLIB_INIT_DECL #define _MYLIB_FINI_DECL #endif 

All other headers in mylib library, e.g., mylib_aux.h, can be of the form:

#ifndef _MYLIB_AUX_H #define _MYLIB_AUX_H #include <mylib.h> _MYLIB_INIT_DECL ... header content ... _MYLIB_FINI_DECL #endif /* _MYLIB_AUX_H */ 

Obviously, the names I'm using are arbitrary, but for multiple library headers, this approach has been useful to me.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.