visual una studio propias propia librerias libreria library incluir create crear creacion compile como borland visual-c++ resources static-libraries

visual-c++ - una - create libraries c++



Recursos de VC++ en una biblioteca estática (7)

¿Es posible construir recursos en una biblioteca estática y reutilizarlos simplemente vinculando con la biblioteca?

Principalmente estoy pensando en el caso en que llamas a una función en la biblioteca que a su vez accede a los recursos.


Acabo de pasar esto con el compilador de MS Visual Studio. Estábamos convirtiendo algunos proyectos heredados de DLL en bibliotecas estáticas. Varias de estas DLL tenían un diálogo o recursos de cadena incrustados en ellas. Pude compilar los scripts .RC para estos archivos DLL en nuestra aplicación principal incluyéndolos en el archivo de script RC de la aplicación principal a través del mecanismo "TEXTINCLUDE". Lo encontré más fácil de hacer editando el archivo RC directamente, pero Visual Studio también proporciona un mecanismo un poco más "mágico". La implementación probablemente sea diferente en otros compiladores.

Para manipular el script RC principal directamente:

.1. En la sección "2 TEXTINCLUDE", incluya el archivo de cabecera que define los ID de recursos para su biblioteca. La sintaxis es

2 TEXTINCLUDE BEGIN "#include ""my_first_lib_header.h""/r/n" "#include ""my_second_lib_header.h""/0" END

.2. En la sección "3 TEXTINCLUDE", incluya el script RC de su biblioteca.

3 TEXTINCLUDE BEGIN "#include ""my_first_library.rc""/r/n" "#include ""my_second_library.rc""/0" END

Los pasos 3 y 4 deberían suceder automáticamente, pero me pareció más confiable ingresarlos yo solo, en lugar de depender del compilador de scripts de recursos de Microsoft para encargarme de todo.

.3. Agregue el archivo de encabezado con sus recursos de bibliotecas define a la lista de símbolos de solo lectura. Esta lista generalmente se encuentra cerca de la parte superior del archivo.

#define APSTUDIO_READONLY_SYMBOLS #include "my_first_lib_header.h" #include "my_second_lib_header.h" #undef APSTUDIO_READONLY_SYMBOLS

.4. Incluya el script RC de su biblioteca en la sección APSTUDIO_INVOKED. Esto generalmente está en la parte inferior del archivo.

#ifndef APSTUDIO_INVOKED #include "my_first_library.rc" #include "my_second_library.rc" #endif

También puede hacer todo esto automáticamente a través del estudio visual IDE, pero descubrí que no siempre se aplicaba cuando lo esperaba.

  1. Abra la ventana "Vista de recursos" en Visual Studio.
  2. Haga clic derecho en el archivo de recursos de su aplicación principal y elija "El recurso incluye ..." en el menú contextual.
  3. En el cuadro etiquetado como "Directivas de símbolos de solo lectura", agregue las instrucciones de inclusión para los archivos .h que definen los ID de recursos para sus bibliotecas.
  4. En el cuadro etiquetado "Directivas de tiempo de compilación", agregue las instrucciones include para el script .rc de su biblioteca.
  5. Haga clic en Aceptar También es posible que desee activar manualmente la compilación del script RC, para asegurarse de que suceda.

Si el script de recursos de su biblioteca hace referencia a cualquier archivo en el disco (archivos de texto, archivos de iconos, etc.), deberá asegurarse de que el proyecto de la aplicación principal sepa dónde encontrarlos. Puede copiar estos archivos en algún lugar donde su aplicación pueda encontrarlos o puede agregar una ruta de inclusión adicional en la configuración del compilador.

Para agregar una ruta de inclusión adicional:

  1. Abra el cuadro de diálogo de propiedades para su aplicación principal.
  2. Seleccione "Propiedades de configuración / Recursos / General" en el panel de navegación de la izquierda.
  3. En la lista de propiedades, ingrese las rutas pertinentes junto a "Incluir directorios adicionales".

Cuando se utiliza el siguiente método, cualquier recurso (en este ejemplo, un ícono) se puede usar como parte integral de una biblioteca estática y dicha biblioteca puede ser utilizada por cualquier tipo de aplicación, incluyendo una de consola (que no tiene cualquier segmento de recursos en absoluto).

  1. El icono se convierte en una matriz estática de BYTE. bin2c se puede usar para eso.
  2. Los datos se convierten en un identificador de HICON. Así es como lo hice:

    HICON GetIcon() { DWORD dwTmp; int offset; HANDLE hFile; HICON hIcon = NULL; offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR); if (offset != 0) { hIcon = CreateIconFromResourceEx(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); } return hIcon; }

  3. Se utiliza GetIcon en lugar de LoadIcon. En lugar de llamar:

m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIcon));

Luego llame

m_hIcon = GetIcon()


La forma recomendada es proporcionar un dll con los recursos junto con su biblioteca.


Lo único que debe hacer para usar recursos (imágenes, diálogos, etc.) en una biblioteca estática en Visual C ++ (2008) es incluir el archivo .res asociado a la biblioteca estática en su proyecto. Esto se puede hacer en "Configuración del proyecto / Enlazador / Entrada / Dependencias adicionales".

Con esta solución, los recursos de la biblioteca estática se empaquetan en .exe, por lo que no necesita una DLL adicional. Lamentablemente, Visual Studio no incluye el archivo .res automáticamente como lo hace para el archivo .lib (cuando se usa la función "dependencias del proyecto"), pero creo que este pequeño paso adicional es aceptable.

He buscado durante mucho tiempo esta solución, y ahora me sorprende que sea así de simple. El único problema es que está totalmente indocumentado.


No lo creo. La biblioteca estática no tiene su propio HINSTANCE. Su código se ejecuta en el contexto de DLL o EXE que lo vincula. Es por eso que todos los recursos que intentará cargar desde el código de la biblioteca estática serán de esa DLL / EXE adjunta.

Sin embargo, hice ese tipo de reutilización de recursos con una DLL, en la medida en que tiene su propio espacio de direcciones, y puede llamar a LoadResource con DLL HINSTANCE.


Se puede hacer, pero es bastante doloroso: no se puede hacer simplemente vinculando con la biblioteca estática.

Considere esto: los recursos están incrustados en un EXE o DLL. Cuando algún código en la biblioteca estática llama (por ejemplo) a LoadIcon, obtendrá los recursos del EXE o DLL con el que está vinculado.

Entonces, si su biblioteca estática requiere recursos para estar disponible, tiene un par de opciones:

  1. Puede hacer que la biblioteca los construya sobre la marcha y luego use (por ejemplo) CreateDialogIndirect . Consulte "Creación de una plantilla de diálogo en tiempo de ejecución" de Raymond Chen.
  2. Puede tenerlos incrustados en la biblioteca como matrices simples (es decir) char my_dialog_resource[] = { .... }; y luego use (por ej.) CreateDialogIndirect . Probablemente necesite encontrar (o escribir) una utilidad que convierta archivos .RES archivos .CPP .
  3. Puede enviar el archivo LIB con un script de recursos (archivo .RC ) y el archivo de encabezado correspondiente. A continuación, #include los #include como relevantes. Deberá reservar un rango de ID de recursos para que utilice el LIB, de modo que no colisionen con los del EXE o DLL principal. Esto es lo que MFC hace cuando se usa como una biblioteca estática. O puede usar ID de recurso de cadena (esto no funciona con recursos STRINGTABLE ).
  4. Su biblioteca estática puede enviarse con una DLL de recursos por separado.

Según Visual Studio 2010, las herramientas de desarrollo de Microsoft aparentemente no pueden manejar los datos de recursos compilados dentro de las bibliotecas estáticas en absoluto.

Para distribuir un archivo de recursos compilados (un archivo .res ), tiene dos opciones:

  1. Distribuya los archivos .res separado e indique al código del cliente que establezca un vínculo con ellos;
  2. Use cvtres para combinar varios archivos .res en un solo archivo de objeto ( .obj ) y proporciónelo por separado.

Tenga en cuenta que no puede lib en los archivos de objetos creados con cvtres . Si se proporcionan varios archivos de objetos, lib queja como si se hubieran dado varios archivos .res ; si se proporciona un solo archivo de objeto, lib no se queja, pero el vinculador simplemente ignora los datos de recursos incrustados en el archivo lib.

Puede ser que exista una forma de forzar al enlazador a leer y vincular el libbed en los datos de recursos (con alguna opción de línea de comandos, manipulación de secciones, etc.), ya que los datos de los recursos están disponibles en la biblioteca (como dumpbin revela). Hasta ahora, no he encontrado una solución y, a menos que uno esté dispuesto a hackear las herramientas de desarrollo, cualquier cosa mejor que esta simple solución probablemente no valga la pena.

La única forma de enviar datos de recursos en una biblioteca estática (en este caso, con una biblioteca estática) es distribuir los recursos por separado y vincularlos explícitamente en el código del cliente. El uso de cvtres puede reducir la cantidad de archivos de recursos distribuidos a uno, si tiene muchos de ellos.