En esta página

Creación de bibliotecas compartidas

Las siguientes secciones enumeran ciertas cosas que deben tenerse en cuenta al crear bibliotecas compartidas.

Uso de símbolos de bibliotecas compartidas

Los símbolos -funciones, variables o clases- contenidos en bibliotecas compartidas destinadas a ser utilizadas por clientes, como aplicaciones u otras bibliotecas, deben marcarse de un modo especial. Estos símbolos se denominan símbolos públicos que se exportan o se hacen visibles públicamente.

El resto de símbolos no deben ser visibles desde el exterior. En la mayoría de las plataformas, los compiladores los ocultan por defecto. En algunas plataformas, se requiere una opción especial del compilador para ocultar estos símbolos.

Al compilar una biblioteca compartida, debe marcarse para su exportación. Para utilizar la biblioteca compartida desde un cliente, algunas plataformas pueden requerir también una declaración especial de importación.

Dependiendo de la plataforma de destino, Qt proporciona macros especiales que contienen las definiciones necesarias:

  • Q_DECL_EXPORT deben añadirse a las declaraciones de los símbolos utilizados al compilar una biblioteca compartida.
  • Q_DECL_IMPORT debe añadirse a las declaraciones de símbolos utilizadas al compilar un cliente que utilice la biblioteca compartida.

Ahora, tenemos que asegurarnos de que se invoca la macro correcta, tanto si compilamos una biblioteca compartida en sí, como si sólo compilamos el cliente que utiliza la biblioteca compartida. Normalmente, esto puede resolverse añadiendo una cabecera especial.

Supongamos que queremos crear una biblioteca compartida llamada mysharedlib. Una cabecera especial para esta biblioteca, mysharedlib_global.h, tiene este aspecto:

#include <QtCore/QtGlobal>

#if defined(MYSHAREDLIB_LIBRARY)
#  define MYSHAREDLIB_EXPORT Q_DECL_EXPORT
#else
#  define MYSHAREDLIB_EXPORT Q_DECL_IMPORT
#endif

En cada cabecera de la biblioteca, especificamos lo siguiente:

#include "mysharedlib_global.h"

MYSHAREDLIB_EXPORT void foo();
class MYSHAREDLIB_EXPORT MyClass...

Luego tenemos que asegurarnos de que MYSHAREDLIB_LIBRARY está definido para el compilador cuando construya la propia biblioteca. Esto se hace en el sistema de compilación de la biblioteca. Si usamos CMake, aumentamos el objetivo de la biblioteca compartida:

target_compile_definitions(mysharedlib PRIVATE MYSHAREDLIB_LIBRARY)

Si usamos qmake, añadimos

DEFINES += MYSHAREDLIB_LIBRARY

al archivo .pro de la biblioteca compartida.

Nota: Los asistentes de biblioteca en Qt Creator y Qt VS Tools le proporcionan un esqueleto que configura estas cosas por usted.

Consideraciones sobre el archivo de cabecera

Normalmente, los clientes incluirán sólo los archivos de cabecera públicos de las bibliotecas compartidas. Estas bibliotecas pueden ser instaladas en una ubicación diferente, cuando se despliegan. Por lo tanto, es importante excluir otros archivos de cabecera internos que se utilizaron al construir la biblioteca compartida.

Por ejemplo, la biblioteca puede proporcionar una clase que envuelve un dispositivo de hardware y contiene un controlador para ese dispositivo, proporcionado por alguna biblioteca de terceros:

#include <footronics/device.h>

class MyDevice {
private:
    FOOTRONICS_DEVICE_HANDLE handle;
};

Una situación similar ocurre con los formularios creados por Qt Widgets Designer cuando se utiliza la agregación o la herencia múltiple:

#include "ui_widget.h"

class MyWidget : public QWidget {
private:
    Ui::MyWidget m_ui;
};

Al desplegar la librería, no debería haber dependencia con las cabeceras internas footronics/device.h o ui_widget.h.

Esto puede evitarse haciendo uso del modismo Pointer to implementation descrito en varios libros de programación C++. Para clases con semántica de valores, considere el uso de QSharedDataPointer.

Compatibilidad binaria

Para que los clientes que cargan una biblioteca compartida funcionen correctamente, la disposición de memoria de las clases utilizadas debe coincidir exactamente con la disposición de memoria de la versión de la biblioteca que se utilizó para compilar el cliente. En otras palabras, la biblioteca encontrada por el cliente en tiempo de ejecución debe ser compatible con la versión utilizada en tiempo de compilación.

Esto no suele ser un problema si el cliente es un paquete de software autónomo que incluye todas las bibliotecas que necesita.

Sin embargo, si la aplicación cliente depende de una biblioteca compartida que pertenece a un paquete de instalación diferente o al sistema operativo, entonces tenemos que pensar en un esquema de versionado para las bibliotecas compartidas y decidir a qué nivel se va a mantener la compatibilidad binaria. Por ejemplo, se garantiza que las bibliotecas Qt del mismo número de versión principal son compatibles en binario.

Mantener la compatibilidad binaria impone algunas restricciones a los cambios que se pueden realizar en las clases. Puede encontrar una buena explicación en KDE - Policies/Binary Compatibility Issues With C++. Estas cuestiones deben tenerse en cuenta desde el principio del diseño de la biblioteca. Recomendamos que se utilice el principio de Ocultar información y la técnica de Puntero a implementación siempre que sea posible.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.