La principal diferencia es que incluye bibliotecas vinculadas estáticas con su aplicación. Están vinculados cuando construyes tu aplicación. Las bibliotecas dinámicas están vinculadas en tiempo de ejecución, por lo que no necesita incluirlas con su aplicación. En estos días, las bibliotecas dinámicas se utilizan para reducir el tamaño de las aplicaciones al tener muchas bibliotecas dinámicas en la computadora de todos.
Las bibliotecas dinámicas también permiten a los usuarios actualizar las bibliotecas sin reconstruir las aplicaciones cliente. Si se encuentra un error en una biblioteca que usa en su aplicación y está vinculada estáticamente, deberá reconstruir su aplicación y volver a publicarla para todos sus usuarios. Si se encuentra un error en una biblioteca vinculada dinámicamente, todos sus usuarios solo necesitan actualizar sus bibliotecas y su aplicación no necesita una actualización.
Cuando se compila un programa en C++. Debe tener referencias a las funciones y el código de la biblioteca de C++ (digamos, por ejemplo, el código de la biblioteca).
Supongamos que tenemos una biblioteca compartida hipotética llamada libdyno.so
. Eventualmente podrá echar un vistazo dentro usando objdump
o nm
.
objdump --syms libdyno.so
Puede hacer esto hoy en su sistema con cualquier biblioteca compartida. objdump
en un MAC se llama gobjdump
y viene con cerveza en el binutils
paquete. Prueba esto en una Mac...
gobjdump --syms /usr/lib/libz.dylib
Ahora puede ver que los símbolos están contenidos en el objeto compartido. Cuando link
con el objeto compartido normalmente usas algo como
g++ -Wall -g -pedantic -ldyno DynoLib_main.cpp -o dyno_main
Tenga en cuenta el -ldyno
en ese comando. Esto le dice al compilador (realmente el enlazador ld) que busque un archivo de objeto compartido llamado libdyno.so
donde normalmente los busca. Una vez que encuentra ese objeto, puede encontrar los símbolos que necesita. No hay dependencia circular porque usted, el desarrollador, solicitó que se cargara la biblioteca dinámica especificando el -l
bandera.
¿Cómo y cuándo usarías una biblioteca dinámica? Cómo haces uno? Como en cuál es el comando de compilación específico que se usa para producir dicho archivo a partir de un archivo .cpp estándar
Cree un archivo llamado DynoLib.cpp
#include "DynoLib.h"
DynamicLib::DynamicLib() {}
int DynamicLib::square(int a) {
return a * a;
}
Cree un archivo llamado DynoLib.h
#ifndef DYNOLIB_H
#define DYNOLIB_H
class DynamicLib {
public:
DynamicLib();
int square(int a);
};
#endif
Compílelos para que sean una biblioteca compartida de la siguiente manera. Esto es específico de Linux...
g++ -Wall -g -pedantic -shared -std=c++11 DynoLib.cpp -o libdyno.so
Ahora puede inspeccionar este objeto usando el comando que di antes, es decir,
objdump --syms libdyno.so
Ahora cree un archivo llamado DynoLib_main.cpp que se vinculará con libdyno.so
y use la función que acabamos de definir en él.
#include "DynoLib.h"
#include <iostream>
using namespace std;
int main(void) {
DynamicLib *lib = new DynamicLib();
std::cout << "Square " << lib->square(1729) << std::endl;
return 1;
}
Compílalo de la siguiente manera
g++ -Wall -g -pedantic -L. -ldyno DynoLib_main.cpp -o dyno_main
./dyno_main
Square 2989441
También puede echar un vistazo al binario principal usando nm
. A continuación, veo si hay algo con la cadena square
en él, es decir, está el símbolo que necesito de libdyno.so
referenciado de alguna manera en mi binario.
nm dyno_runner |grep square
U _ZN10DynamicLib6squareEi
La respuesta es sí. La mayúscula U
significa indefinido, pero este es el nombre del símbolo para nuestro método cuadrado en la clase DynamicLib que creamos anteriormente. El nombre de aspecto extraño se debe a la manipulación de nombres, que es un tema propio.
¿Cómo sé a cuáles enlazar estáticamente como lo haría con un archivo normal.o y cuáles se supone que deben enlazarse dinámicamente?
No necesitas saberlo. Usted especifica con qué desea vincular y deja que el compilador (y el vinculador, etc.) haga el trabajo. Tenga en cuenta el -l
bandera nombra la biblioteca y el -L
le dice dónde mirar. Hay un artículo decente sobre cómo el compilador encuentra algo aquí
Opción de enlace gcc -L:formas alternativas de especificar la ruta a la biblioteca dinámica
O echa un vistazo a man ld
.
¿Para qué sirven las banderas -L y -l? ¿Qué significa especificar, por ejemplo, un indicador -lusb en la línea de comando?
Ver el enlace de arriba. Esto es de man ld
..
-L directorio de búsqueda
Agregue path searchdir a la lista de rutas en las que ld buscará bibliotecas de archivo y scripts de control de ld. Puede usar esta opción cualquier número de veces. Los directorios se buscan en el orden en que se especifican en la línea de comando. Los directorios especificados en la línea de comando se buscan antes que los directorios predeterminados. Todas las opciones -L se aplican a todas las opciones -l, independientemente del orden en que aparezcan las opciones. Las opciones -L no afectan cómo ld busca un linkerscript a menos que se especifique la opción -T.`
Si logró llegar aquí, vale la pena aprender sobre el enlazador, es decir, ld. Desempeña un trabajo importante y es fuente de mucha confusión porque la mayoría de las personas comienzan a trabajar con un compilador y piensan que compiler == linker
y esto no es cierto.