titulo - Enlace de la biblioteca estática compilada de C al programa C++
como poner varios colores en c++ (2)
Intenté vincular una biblioteca estática (compilada con gcc) a un programa c ++ y obtuve una "referencia indefinida". Utilicé gcc y g ++ versión 4.6.3 en una máquina de servidor ubuntu 12.04. Por ejemplo, aquí está el archivo de biblioteca simple para el método factorial:
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);
}
Creé el objeto para este mylib.c usando gcc:
gcc -o mylib.o -c mylib.c
Nuevamente, la biblioteca estática se creó a partir del archivo de objeto utilizando la utilidad AR:
ar -cvq libfact.a mylib.o
Probé esta biblioteca con un programa en C (test.c) y un programa en C ++ (test.cpp)
Tanto el programa C como el C ++ tienen el mismo cuerpo:
#include "mylib.h"
int main()
{
int fact = factorial(5);
return 0;
}
Suponiendo que la biblioteca estática libfact.a está disponible en el directorio / home / test, compilé mi programa C sin ningún problema:
gcc test.c -L/home/test -lfact
Sin embargo, al probar el programa C ++, se produjo un error de enlace:
g++ test.cpp -L/home/test -lfact
test.cpp:(.text+0x2f): undefined reference to `factorial(int)''
collect2: ld returned 1 exit status
Incluso intenté agregar un comando externo en test.cpp:
extern int factorial(int n) //added just before the main () function
Sigue siendo el mismo error.
- ¿Alguien puede decirme en qué estoy equivocado aquí?
- ¿Hay algo que me perdí al crear la biblioteca estática?
- ¿Tengo que agregar algo en mi
test.cpp
para que funcione?
El problema es que no le has dicho a tu programa de C ++ que el factorial está escrito en C. Necesitas cambiar el archivo de cabecera test.h. Me gusta esto
#ifndef __MYLIB_H_
#define __MYLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
int factorial(int n);
#ifdef __cplusplus
}
#endif
#endif
Ahora su archivo de encabezado debería funcionar para los programas C y C ++. Vea here para más detalles.
Los nombres BTW que contienen un subrayado doble están reservados para el compilador (también lo son los nombres que comienzan con un guión bajo y una letra mayúscula), por lo que #ifndef __MYLIB_H_
es ilegal en sentido estricto. Cambiaría a #ifndef MYLIB_H #define MYLIB_H
Si bien la respuesta aceptada es absolutamente correcta, pensé que solo agregaría una observación. Algunos editores tienen problemas con la llave de apertura / cierre, y sangrarán todo el ámbito extern "C"
en el encabezado. Si mylib.h
es un encabezado clave para una biblioteca, podría considerar:
#if defined (__cplusplus)
#define _MYLIB_INIT_DECL extern "C" {
#define _MYLIB_FINI_DECL }
#else
#define _MYLIB_INIT_DECL
#define _MYLIB_FINI_DECL
#endif
Todos los demás encabezados en la biblioteca mylib
, por ejemplo, mylib_aux.h
, pueden tener la forma:
#ifndef _MYLIB_AUX_H
#define _MYLIB_AUX_H
#include <mylib.h>
_MYLIB_INIT_DECL
... header content ...
_MYLIB_FINI_DECL
#endif /* _MYLIB_AUX_H */
Obviamente, los nombres que estoy usando son arbitrarios, pero para varios encabezados de biblioteca, este enfoque me ha sido útil.